diff --git a/.circleci/config.yml b/.circleci/config.yml index 4ae3eb9a..20edc98f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,6 +17,7 @@ jobs: name: Run Tests command: | make test + no_output_timeout: 30m - store_test_results: path: /home/circleci/project/tests/test-reports - store_artifacts: diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 38af1c27..9df6ca8b 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -3,7 +3,7 @@ name: Bug report about: Provide the details of the bug to us in order to further triage and fix title: "[BUG]" labels: bug -assignees: li-wu, GordonWang +assignees: lephino, arctan5x, jmeixensperger, li-wu, GordonWang --- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 30a5b6f2..046874e8 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -3,7 +3,7 @@ name: Feature request about: Suggest an idea or improvement for this project title: "[FEATURE/IMPROVEMENT]" labels: enhancement -assignees: li-wu, GordonWang +assignees: lephino, arctan5x, jmeixensperger, li-wu, GordonWang --- diff --git a/.gitignore b/.gitignore index 228e620a..d0e9c0ba 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,6 @@ stage/ local/ eventgen_wsgi.conf *.log -dist *.egg-info **/*.tgz .cache @@ -27,3 +26,4 @@ _book *.result venv/* *.log.* +splunk_eventgen-*/ diff --git a/.yapfignore b/.yapfignore new file mode 100644 index 00000000..85fef0c5 --- /dev/null +++ b/.yapfignore @@ -0,0 +1,2 @@ +splunk_eventgen/lib/concurrent +splunk_eventgen/lib/requests_futures diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 38ab06bd..f418bcb2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,99 +1,16 @@ # Contributing -When contributing to this repository, please first discuss the change you wish to make via issue, -email, or any other method with the owners of this repository before making a change. +When contributing to this repository, please read over the [contributing document](http://splunk.github.io/eventgen/CONTRIBUTE.html). [Create a issue](http://splunk.github.io/eventgen/FILE_ISSUES.html) to discuss your demand and follow the [guidelines](http://splunk.github.io/eventgen/CONTRIBUTE_CODE.html) to make the code change -Please note we have a code of conduct, please follow it in all your interactions with the project. +Please note we have a [code of conduct](http://splunk.github.io/eventgen/CONTRIBUTE.html#code-of-conduct), please follow it in all your interactions with the project. -## Pull Request Process - -1. Ensure any install or build dependencies are removed before the end of the layer when doing a - build. -2. Update the splunk_eventgen/README/eventgen.conf.spec with details of changes to the interface, this includes new environment - variables, exposed ports, useful file locations and container parameters. Also, update the necessary documentation. -3. Increase the version numbers in splunk_eventgen/version.json. The versioning scheme we use is [SemVer](http://semver.org/). -4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you - do not have permission to do that, you may request the second reviewer to merge it for you. - -## Code of Conduct - -### Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -### Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or -advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -### Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -### Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -### Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at tonyl@splunk.com. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -### Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ ### Past / Active(marked as *) Contributors bbingham* arctan5x* jmeixensperger* +li-wu* +GordonWang* coccyx Jaykul allanwsplk diff --git a/Makefile b/Makefile index 19969eb9..559bd63b 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ XLARGE ?= 'tests/xlarge' NEWLY_ADDED_PY_FILES = $(shell git ls-files -o --exclude-standard | grep -E '\.py$$') CHANGED_ADDED_PY_FILES = $(shell git ls-files -mo --exclude-standard | grep -E '\.py$$') -.PHONY: tests, lint, format +.PHONY: tests, lint, format, docs all: egg @@ -24,7 +24,7 @@ image: setup_eventgen egg rm splunk_eventgen/default/eventgen_engine.conf || true docker build -f dockerfiles/Dockerfile . -t eventgen -test: egg image test_helper test_collection_cleanup +test: egg image test_helper run_tests test_collection_cleanup test_helper: docker run -d -t --net=host -v /var/run/docker.sock:/var/run/docker.sock --name ${EVENTGEN_TEST_IMAGE} eventgen:latest cat @@ -41,15 +41,10 @@ test_helper: @echo 'Installing test requirements' docker exec -i ${EVENTGEN_TEST_IMAGE} /bin/sh -c "pip install -r $(shell pwd)/tests/requirements.txt" || true +run_tests: @echo 'Running the super awesome tests' docker exec -i ${EVENTGEN_TEST_IMAGE} /bin/sh -c "cd $(shell pwd); python tests/run_tests.py ${SMALL} ${MEDIUM} ${LARGE} ${XLARGE}" || true - echo 'Collecting results' - #TODO: Should be paramaterized or generalized so that we don't need to add this here - docker cp ${EVENTGEN_TEST_IMAGE}:$(shell pwd)/tests_results.xml tests_results.xml || echo "no tests_results.xml" || true - - docker stop ${EVENTGEN_TEST_IMAGE} || true - test_collection_cleanup: @echo 'Collecting results' #TODO: Should be paramaterized or generalized so that we don't need to add this here @@ -97,9 +92,7 @@ run_controller: eg_network docker run --name eg_controller --network eg_network -d -p 5672:5672 -p 15672:15672 -p 9500:9500 eventgen:latest controller docs: - npm install -g gitbook-serve - cd docs/ - gitbookserve + cd docs/; bundle install; bundle exec jekyll serve build_spl: clean python -m splunk_eventgen build --destination ./ @@ -124,3 +117,9 @@ else @yapf -i $(NEWLY_ADDED_PY_FILES) endif +lint-all: + @flake8 . + +format-all: + @isort -rc . + @yapf -r -i . diff --git a/README.md b/README.md index 06670a58..36080834 100644 --- a/README.md +++ b/README.md @@ -33,4 +33,4 @@ The Splunk Event Generator is licensed under the Apache License 2.0. Details can ### Support This software is released as-is. Splunk provides no warranty and no support on this software. -If you have any issues with the software, please file an issue (https://github.com/splunk/eventgen/issues/new) +If you have any issues with the software, please read over the [guidelines](http://splunk.github.io/eventgen/FILE_ISSUES.md) and file an issue. \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..ca35be08 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +_site diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 4c185ab7..bcb926cb 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -19,7 +19,7 @@ These requirements have led to this new architecture in verison 4. Eventgen is * Handles flattening of configs from global defaults and individual config files * Loading Plugins * Load plugins from the `lib/plugins` directory or App's `bin` directories, with three types of Plugins: Rating, Generator and Output - * For more detail on writing plugins, see the [Plugins documentation](Plugins.md) + * For more detail on writing plugins, see the [Plugins documentation](PLUGINS.md) * Creating timers for each sample * For samples with queueable generators (meaning we can have multiple threads generating sample simultaneously), the timer wakes up every interval and puts a task in the queue to be generated by a generator worker * For samples which are not queueable (meaning we can only run one simultaneous thread of the generator), the thread runs the generator plugin single threaded and handles sleeping the proper amount to manage intervals. @@ -38,13 +38,13 @@ Depending on tunable parameters, these can be threads or processes and can eithe # Scaling -This queue architecture allows significant advantages by distributing processing. At each timer execution a generation job gets put in the queue. This queue by default is a Python Queue (either in queue.Queue or multiprocessing.Queue). For details, see the [Performance guide](Performance.md) +This queue architecture allows significant advantages by distributing processing. At each timer execution a generation job gets put in the queue. This queue by default is a Python Queue (either in queue.Queue or multiprocessing.Queue). For details, see the [Performance guide](PERFORMANCE.md) # Testing Given the complexity and the reimplementation of a number of features during refactors, we've also built out a number of test examples. We currently don't have test scripts built with assertions etc, but there are a series of configs and samples under the `tests/` directory which should demonstrate and allow testing of basic functionality. Check out the ``tests/sample_eventgen_conf`` directory in the project for commonly-used plugins and configurations. You can execute a test config by doing: - python bin/eventgen.py generate tests//.conf + python -m splunk_eventgen generate tests//.conf # Server-Controller Architecture diff --git a/docs/BASICS.md b/docs/BASICS.md index 4762eb87..b02b1cc3 100644 --- a/docs/BASICS.md +++ b/docs/BASICS.md @@ -7,14 +7,17 @@ This should hopefully get you through setting up a working eventgen instance. Fo The first example we'll show you should likely cover 90% of the use cases you can imagine. Eventgen can take an export from another Splunk instance, or just a plain text file, and replay those events while replacing the time stamps. Eventgen will pause the amount of time between each event just like it happened in the original, so the events will appear to be coming out in real time. When Eventgen reaches the end of the file, it will automatically start over from the beginning. -### Making a Splunk export +### Making a Splunk Export -To build a seed for your new Eventgen, I recommend taking an export from an existing Splunk instance. You could also take a regular log file and use it for replay (in which case, you can omit sampletype=csv). There are a few considerations. First, Eventgen assumes its sample files are in chronological order. Second, it only uses index, host, source, sourcetype and \_raw fields. To accommodate that, whatever search you write, we recommend appending '| reverse | fields index, host, source, sourcetype, _raw' to your Splunk search and then doing an export to CSV format. Third, make sure you find all the different time formats inside the log file and set up tokens to replace for them, so limiting your initial search to a few sourcetypes is probably advisable. +To build a seed for your new Eventgen, I recommend taking an export from an existing Splunk instance. You could also take a regular log file and use it for replay (in which case, you can omit sampletype=csv). There are a few considerations. +* First, Eventgen assumes its sample files are in chronological order. +* Second, it only uses `index`, `host`, `source`, `sourcetype` and `_raw` fields. To accommodate that, whatever search you write, we recommend appending `| reverse | fields index, host, source, sourcetype, _raw` to your Splunk search and then doing an export to CSV format. +* Third, make sure you find all the different time formats inside the log file and set up tokens to replace for them, so limiting your initial search to a few sourcetypes is probably advisable. ### Running the example -You can easily run these examples by hand. In fact, for testing purposes, I almost always change outputMode = stdout to visually examine the data. Run the command below from the base directory of Eventgen. +You can easily run these examples by hand. In fact, for testing purposes, I almost always change outputMode = stdout to visually examine the data. Run the command below from directory `$EVENTGEN_HOME/splunk_eventgen`. - python -m splunk_eventgen generate splunk_eventgen/README/eventgen.conf.tutorial1 + python -m splunk_eventgen generate README/eventgen.conf.tutorial1 You should now see events showing up on your terminal window. You can see Eventgen will sleep between events as it sees gaps in the events in the source log. @@ -23,9 +26,9 @@ This will cover most, if not all, of most people's use cases. Find a real world ## Basic Sample -Next, lets build a basic noise generator from a log file. This will use sample mode, which take a file and replay all or a subset of that file every X seconds, defined by the interval. Sample mode is the original way eventgen ran, and it's still very useful for generating random data where you want to engineer the data generated from the ground up. To run the example: +Next, lets build a basic noise generator from a log file. This will use sample mode, which take a file and replay all or a subset of that file every X seconds, defined by the interval. Sample mode is the original way eventgen ran, and it's still very useful for generating random data where you want to engineer the data generated from the ground up. Run the command below from directory `$EVENTGEN_HOME/splunk_eventgen`: - python -m splunk_eventgen generate splunk_eventgen/README/eventgen.conf.tutorial2 + python -m splunk_eventgen generate README/eventgen.conf.tutorial2 ### Grabbing and rating events @@ -67,7 +70,7 @@ Let's us decide how often we want to generate events and how we want to generate randomizeEvents = true Eventgen by default will rate events by the time of day and the day of the week and introduce some randomness every interval. Also by default, we'll only grab the first X events from the log file every time. For this example, we're looking at router and switch events, which actually is the opposite of the normal business flow. We expect to see more events overnight for a few hours during maintenance windows and calm down during the day, so we'll need to override the default rating which looks like a standard business cycle. -hourOfDayRate is a JSON formatted hash, with a string identifier for the current hour and a float representing the multiplier we want to use for that hour. In general, I've always configured the rate to be between 0 and 1, but nothing limits you from putting it at any valid floating point value. dayOfWeekRate is similar, but the number is the day of the week, starting with Sunday. In this example, Saturday and Sunday early mornings should have the greatest number of events, with fewer events evenly distributed during the week. randomizeCount says to introduce 20% randomess, which means plus or minus 10% of the rated total, to every rated count just to make sure we don't have a flat rate of events. randomizeEvents we discussed previously, it makes sure we don't grab the same lines from the file every time. +`hourOfDayRate` is a JSON formatted hash, with a string identifier for the current hour and a float representing the multiplier we want to use for that hour. In general, I've always configured the rate to be between 0 and 1, but nothing limits you from putting it at any valid floating point value. `dayOfWeekRate` is similar, but the number is the day of the week, starting with Sunday. In this example, Saturday and Sunday early mornings should have the greatest number of events, with fewer events evenly distributed during the week. `randomizeCount` says to introduce 20% randomness, which means plus or minus 10% of the rated total, to every rated count just to make sure we don't have a flat rate of events. `randomizeEvents` we discussed previously, it makes sure we don't grab the same lines from the file every time. outputMode = file fileName = /tmp/ciscosample.log @@ -81,7 +84,7 @@ As we've seen before, here's a simple token substitution for the timestamp. Thi Let's look in detail at this configuration format. token is the configuration statement, 0 is the token number (we'll want a different number for every token we define, although they can be non-contiguous). The third part defines the three subitems of token configuration. The first, token, defines a regular expression we're going to look for in the events as they stream through Eventgen. The second, replacementType, defines what type of replacement we're going to need. This is a timestamp, but we also offer a variety of other token replacement types such as random for randomly generated values, file for grabbing lines out of files, static for replacing with static strings, etc. We'll cover those in detail later. The third subitem, replacement, is specific for the replacementType, and in this case defines a strptime format we're going to use to output the time using strftime. For a reference on how to configure strptime, check python's documentation on strptime format strings. -This should now replay random events from the file we have configured. Go ahead and cd to $EVENTGEN\_HOME/bin and run python eventgen.py ../README/eventgen.conf.tutorial1. In another shell, tail -f /tmp/ciscosample.log and you should see events replaying from the cisco.sample file! You can reuse this same example to easily replay a customer log file, of course accounting for the different regular expressions and strptime formats you'll need for their timestamps. Remember to customize interval, earliest, and count for the number of events you want the generator to build. +This should now replay random events from the file we have configured. Go ahead and cd to `$EVENTGEN_HOME/splunk_eventgen` and run `python -m splunk_eventgen generate README/eventgen.conf.tutorial1`. In another shell, tail -f /tmp/ciscosample.log and you should see events replaying from the cisco.sample file! You can reuse this same example to easily replay a customer log file, of course accounting for the different regular expressions and strptime formats you'll need for their timestamps. Remember to customize interval, earliest, and count for the number of events you want the generator to build. ## Second example, building events from scratch @@ -151,7 +154,7 @@ Note here that we've specified index, host, source and sourceType. In the past ### Defining tokens -If you look at the sample.tutorial3 file, you'll see that we took just one sample event and placed it in the file. Eventgen will look at this one event, continue to replay it a number of times defined by our rating parameters, and then substitute in tokens we're going to define. First, let's get the one token we understand out of the way, the timestamp: +If you look at the `sample.tutorial3` file, you'll see that we took just one sample event and placed it in the file. Eventgen will look at this one event, continue to replay it a number of times defined by our rating parameters, and then substitute in tokens we're going to define. First, let's get the one token we understand out of the way, the timestamp: token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} token.0.replacementType = timestamp @@ -237,29 +240,27 @@ Secondly, in the replacement clause, we have a JSON formatted list. This allows ## Command Line -This revision of Eventgen can be run by itself from a command line for testing. This means you can simply run bin/eventgen.py and start seeing output, which is great for testing. Please note to do this you'll want to set the $SPLUNK\_HOME environment variable properly so your configurations will work. **Command Line and Embedded Defaults are defined in the lib/eventgen\_defaults file in the [global] stanza**. +This revision of Eventgen can be run by itself from a command line for testing. This means you can simply run `splunk_eventgen generate eventgen.conf` and start seeing output, which is great for testing. **Command Line and Embedded Defaults are defined in the `splunk_eventgen/default/eventgen.conf` file in the [global] stanza**. ## Splunk App -The original SA-Eventgen was written as a Splunk app, and this Eventgen release supports that deployment method as well. In this deployment method, we will read configurations through Splunk's internal REST interface for grabbing config info, and Eventgen will look for configurations in every installed apps default and local directories in eventgen.conf file. This is how ES is deployed, and it provides a very good example of this deployment method. If you are writing a complicated Splunk application which will be deployed in multiple Applications, like ES, this is the recommended deployment method as it will simply your needs of building scripted inputs for each of those individual applications. Installed a separate application, there is also a setup.xml provided which allows for easy disabling of the scripted input in Eventgen application. **Defaults are defined in the default/eventgen.conf file in App mode**. +The original `SA-Eventgen` was written as a Splunk app, and this Eventgen release supports that deployment method as well. In this deployment method, we will read configurations through Splunk's internal REST interface for grabbing config info, and Eventgen will look for configurations in every installed apps default and local directories in `eventgen.conf` file. This is how ES is deployed, and it provides a very good example of this deployment method. If you are writing a complicated Splunk application which will be deployed in multiple Applications, like ES, this is the recommended deployment method. -In your app's eventgen.conf file, sample files for file, mvfile and seqfile substitution should be referenced using `$SPLUNK_HOME/etc/apps//samples/`. +Install the latest SA-Eventgen App. There is no additional configuration required. SA-Eventgen app will automatically identify with any apps with `eventgen.conf`. -## Scripted Input +To start generating data, simply enable the SA-Eventgen modinput by going to Settings > Data Inputs > SA-Eventgen and by clicking "enable" on the default modular input stanza. -If you are writing an Eventgen for one application, like the Operational Intelligence demo, bundling two applications together is more complex than required and complicates distribution. In this case, Eventgen supports being deployed as a scripted input inside your application. **Note, you must set 'passAuth = splunk-system-user' in your inputs.conf for this to work**. An example inputs.conf entry: +If you wish you add your bundle so that the modinput can detect your package: +Package your `eventgen.conf` and sample files into a directory structure as outlined in the [configuration](CONFIGURE.md). After that's done, copy/move the bundle into your `${SPLUNK_HOME}/etc/apps/` directory and restart Splunk. If you have specific samples enabled in your `eventgen.conf`, you should see data streaming into the specified Splunk index. - [script://./bin/eventgen.py] - disabled = false - interval = 300 - passAuth = splunk-system-user - sourcetype = eventgen - index = _internal - -Note, the interval can be set to anything. Eventgen will stay running as soon as Splunk launches it. To embed Eventgen into your application, you need to include everything in the bin and lib directories in your application. In Scripted Input mode, we also read eventgen-standalone.conf in the default and local directories, and again **it will not flatten these configurations, so the local file will completely override the default**. It is recommended that when deploying standalone, you only write one configuration file in the local directory. Remember to copy any stock samples you are using into your apps samples directory as well. **Defaults are defined in the lib/eventgen\_defaults file in the [global] stanza**. - -In your app's eventgen.conf file, sample files for file, mvfile and seqfile substitution should be referenced using `$SPLUNK_HOME/etc/apps//samples/`. +Make sure the bundle app permission is global. You can config this in two ways: +* Log in to Splunk Web and navigate to Apps > Manage Apps. Find the bundle app row and set the permission to 'Global' on the Sharing column. +* Create a folder `metadata` under the bundle with file `default.meta` and add the following content: +``` +[] +export=system +``` ## Wrapping up -We hope the tutorial covers most use cases you would need. If you have something you're struggling to model, please reach out to Tony Lee (tonyl@splunk.com). We believe we can cover just about anything you'd want to model with this Eventgen, but if not, we're happy to add features to the software so that everyone can benefit! \ No newline at end of file +We hope the tutorial covers most use cases you would need. If you have something you're struggling to model, please reach out to Tony Lee (tonyl@splunk.com). We believe we can cover just about anything you'd want to model with this Eventgen, but if not, we're happy to add features to the software so that everyone can benefit! diff --git a/docs/CONTRIBUTE.md b/docs/CONTRIBUTE.md new file mode 100644 index 00000000..51135f9b --- /dev/null +++ b/docs/CONTRIBUTE.md @@ -0,0 +1,97 @@ +# Contribute to Eventgen + +Please be sure to read the contribution guidelines before making or requesting a change. + +## Code of conduct + +### Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + + +### Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +### Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +### Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at tonyl@splunk.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ + +## Filing issues + +Before filing an issue, please be sure to read the guidelines for what you're reporting: + +* [Reporting bugs](FILE_ISSUES.md#reporting-bugs) +* [Requesting changes](FILE_ISSUES.md#requesting-changes) + + +## Contributing code + +Before working on the code, please read over the guidelines about how to contributing code. + +* [Pull Request](CONTRIBUTE_CODE.md#pull-request-guidelines) +* [Build Eventgen](CONTRIBUTE_CODE.md#how-to-build-eventgen) +* [Code Style](CONTRIBUTE_CODE.md#code-style-and-formatting-tools) + + diff --git a/docs/CONTRIBUTE_CODE.md b/docs/CONTRIBUTE_CODE.md new file mode 100644 index 00000000..14c4453d --- /dev/null +++ b/docs/CONTRIBUTE_CODE.md @@ -0,0 +1,140 @@ +# Contribute Code To Eventgen + +If you want to contribute code to eventgen, please read over the following guidelines before creating any pull request. + + +## Pull request guidelines + + +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. + +### Get started + +If you’d like to work on a pull request and you’ve never submitted code before, follow these steps: +1. fork eventgen to your github workspace +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. + + +After that, you’re ready to start working on code. + +### Working on the code + +The process of submitting a pull request is fairly straightforward and generally follows the same pattern each time: +1. Create a new branch +2. Make your changes and check into local branch +3. Rebase onto upstream +4. Run the test +5. Push your change +6. Submit the pull request + +#### Step1: Create a new branch + +The first step to sending a pull request is to create a new branch in your eventgen fork. Give the branch a descriptive name that describes what it is you’re fixing. Although the branch name can be any words, we highly recommend you to use some descriptive and structured name. It will be good for you to manage the branches when there are many branches in your fork. +```bash +# The branch name contains 2 parts. First part works like a label, it describe what type of issue this branch is working on. Second part is the issue id. +# For example, if the code change is a bug fix +$ git checkout -b bug/issue123 +# For example, if the code change is to address change request +$ git checkout -b change/issue123 +# For example, if the code change is only about refine the build process, such as making changes about CICD process +$ git checkout -b build/issue123 +# For example, if the code change is only about refining the test cases or paying for tech debt +$ git checkout -b chore/issue123 +``` + +#### Step2: Make your changes and check into local branch + +Once you finished your change, commit them into your local branch. +```bash +$ git add -A +$ git commit +``` + +Our commit message format is as follows: +``` +Tag: Short description (fixes #1234) +// empty line +Longer description here if necessary +``` + +The first line of the commit message (the summary) must have a specific format. This format is checked by our build tools. + +The **Tag** is one of the following: + +* **Fix** - for a bug fix. +* **Update** - update or enhance an existing feature. +* **New** - implemented a new feature. +* **Docs** - changes to documentation only. +* **Build** - changes to build process only, updating the dependency libs etc. +* **Chore** - for refactoring, adding tests, paying tech debt etc. (anything that isn’t user-facing). + + +Use the labels of the issue you are working on to determine the best tag. + +The message summary should be a one-sentence description of the change, and it must be 72 characters in length or shorter. Please make the short description concise. If the pull request addresses an issue, then the issue number should be mentioned at the end. If the commit doesn’t completely fix the issue, then use (refs #1234) instead of (fixes #1234). + +**Note**: please squash you changes in one commit before firing the pull request. One commit in one PR keeps the git history clean. + +#### Step 3: Rebase onto upstream + +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. +```bash +git fetch upstream +git rebase upstream/master +``` + +#### Step 4: Run the tests + +The is a place holder as well. We should write about +* how to run unit test +* how to run funcional test +* what is the acceptance criteria about the test +* how to add test cases + + +#### Step 5: Push your change +Before pushing the changes, double check your changes follows the [code style](#code-style-and-formatting-tools) and all tests are passed. + + +Next, push your changes to your clone: +```bash +git push origin fix/issue123 +``` + +#### Step 6: Submit the pull request + +Before creating a pull request, here are some recommended **check points**. + +1. Ensure any install or build dependencies are removed before the end of the layer when doing a + build. +2. Update the splunk_eventgen/README/eventgen.conf.spec with details of changes to the interface, this includes new environment + variables, exposed ports, useful file locations and container parameters. Also, update the necessary documentation. +3. Make sure the build is successful and all test cases are passed. +4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you + do not have permission to do that, you may request the second reviewer to merge it for you. + + +Next, create a pull request from your branch to the eventgen develop branch. +Mark @lephino , @arctan5x , @jmeixensperger , @li-wu , @GordonWang as the reviewers. + + + +## Code style and formatting tools + +Since Eventgen is written in python, we apply a coding style based on [PEP8](https://www.python.org/dev/peps/pep-0008/). + + +**TODO: Add section refrencing the code formatter.** + + +## How to build eventgen + +**TODO: consolidate the setup page information into this section.** + +### Build eventgen pip module + +### Build eventgen splunk app + +### Run unit test + +### Run functional test \ No newline at end of file diff --git a/docs/Dockerfile b/docs/Dockerfile deleted file mode 100644 index 46e7dff7..00000000 --- a/docs/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -FROM alpine:3.6 - -# Install stuff -RUN apk upgrade --update && \ - apk add --no-cache --update \ - nodejs \ - nodejs-npm \ - curl \ - python3 \ - build-base && \ - rm -rf /var/cache/apk/* && \ - npm install -g npm q gitbook-cli lodash commander optimist bash-color fs-extra - -# Copy gitbook files -COPY *.md /root/ -COPY book.json /root/ - -# Copy entrypoint -COPY entrypoint.sh /sbin/entrypoint.sh - -# Run gitbook install -RUN cd /root/ && gitbook install - -EXPOSE 4000 - -HEALTHCHECK --interval=1m --timeout=15s --start-period=1m --retries=3 \ - CMD curl -f http://localhost:4000 || exit 1 - -WORKDIR /root/ -ENTRYPOINT ["/sbin/entrypoint.sh"] diff --git a/docs/FILE_ISSUES.md b/docs/FILE_ISSUES.md new file mode 100644 index 00000000..018d85f6 --- /dev/null +++ b/docs/FILE_ISSUES.md @@ -0,0 +1,20 @@ +# Filing Issues For Eventgen + +## Reporting bugs + + +If you think you've found a bug in eventgen, please [create a bug report](https://github.com/splunk/eventgen/issues/new/choose) on github. + + +For bugs, please choose the bug report template. Then, provide information as much as possible according to the tempalte. If we need to triage issues and constantly ask people for more detail, that’s time taken away from actually fixing issues. Help us be as efficient as possible by including a lot of detail in your issues. + +**Note:** If you just have a question that won’t necessarily result in a change to eventgen, such as asking how something works or how to contribute, please use the slack channel instead of filing an issue. + + +## Requesting changes + + +If you want some enhancement or new feature which is not in current eventgen release, please [create a feature request](https://github.com/splunk/eventgen/issues/new/choose) on github. + + +For change requests, please choose the feature request template. Then, provide the information as much as possible according to the template. When creating a change request issue, please provide clear description about the user scenario and the expected behavior following to the template. It is very important to save the time and avoid back and forth discussion. \ No newline at end of file diff --git a/docs/Gemfile b/docs/Gemfile new file mode 100644 index 00000000..37f5eaa4 --- /dev/null +++ b/docs/Gemfile @@ -0,0 +1,2 @@ +source 'https://rubygems.org' +gem 'github-pages', group: :jekyll_plugins diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock new file mode 100644 index 00000000..057c847b --- /dev/null +++ b/docs/Gemfile.lock @@ -0,0 +1,248 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (4.2.10) + i18n (~> 0.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.11.1) + colorator (1.1.0) + commonmarker (0.17.13) + ruby-enum (~> 0.5) + concurrent-ruby (1.1.5) + dnsruby (1.61.2) + addressable (~> 2.5) + em-websocket (0.5.1) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0.6.0) + ethon (0.12.0) + ffi (>= 1.3.0) + eventmachine (1.2.7) + execjs (2.7.0) + faraday (0.15.4) + multipart-post (>= 1.2, < 3) + ffi (1.10.0) + forwardable-extended (2.6.0) + gemoji (3.0.0) + github-pages (197) + activesupport (= 4.2.10) + github-pages-health-check (= 1.16.1) + jekyll (= 3.7.4) + jekyll-avatar (= 0.6.0) + jekyll-coffeescript (= 1.1.1) + jekyll-commonmark-ghpages (= 0.1.5) + jekyll-default-layout (= 0.1.4) + jekyll-feed (= 0.11.0) + jekyll-gist (= 1.5.0) + jekyll-github-metadata (= 2.12.1) + jekyll-mentions (= 1.4.1) + jekyll-optional-front-matter (= 0.3.0) + jekyll-paginate (= 1.1.0) + jekyll-readme-index (= 0.2.0) + jekyll-redirect-from (= 0.14.0) + jekyll-relative-links (= 0.6.0) + jekyll-remote-theme (= 0.3.1) + jekyll-sass-converter (= 1.5.2) + jekyll-seo-tag (= 2.5.0) + jekyll-sitemap (= 1.2.0) + jekyll-swiss (= 0.4.0) + jekyll-theme-architect (= 0.1.1) + jekyll-theme-cayman (= 0.1.1) + jekyll-theme-dinky (= 0.1.1) + jekyll-theme-hacker (= 0.1.1) + jekyll-theme-leap-day (= 0.1.1) + jekyll-theme-merlot (= 0.1.1) + jekyll-theme-midnight (= 0.1.1) + jekyll-theme-minimal (= 0.1.1) + jekyll-theme-modernist (= 0.1.1) + jekyll-theme-primer (= 0.5.3) + jekyll-theme-slate (= 0.1.1) + jekyll-theme-tactile (= 0.1.1) + jekyll-theme-time-machine (= 0.1.1) + jekyll-titles-from-headings (= 0.5.1) + jemoji (= 0.10.2) + kramdown (= 1.17.0) + liquid (= 4.0.0) + listen (= 3.1.5) + mercenary (~> 0.3) + minima (= 2.5.0) + nokogiri (>= 1.8.5, < 2.0) + rouge (= 2.2.1) + terminal-table (~> 1.4) + github-pages-health-check (1.16.1) + addressable (~> 2.3) + dnsruby (~> 1.60) + octokit (~> 4.0) + public_suffix (~> 3.0) + typhoeus (~> 1.3) + html-pipeline (2.10.0) + activesupport (>= 2) + nokogiri (>= 1.4) + http_parser.rb (0.6.0) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + jekyll (3.7.4) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 0.7) + jekyll-sass-converter (~> 1.0) + jekyll-watch (~> 2.0) + kramdown (~> 1.14) + liquid (~> 4.0) + mercenary (~> 0.3.3) + pathutil (~> 0.9) + rouge (>= 1.7, < 4) + safe_yaml (~> 1.0) + jekyll-avatar (0.6.0) + jekyll (~> 3.0) + jekyll-coffeescript (1.1.1) + coffee-script (~> 2.2) + coffee-script-source (~> 1.11.1) + jekyll-commonmark (1.3.1) + commonmarker (~> 0.14) + jekyll (>= 3.7, < 5.0) + jekyll-commonmark-ghpages (0.1.5) + commonmarker (~> 0.17.6) + jekyll-commonmark (~> 1) + rouge (~> 2) + jekyll-default-layout (0.1.4) + jekyll (~> 3.0) + jekyll-feed (0.11.0) + jekyll (~> 3.3) + jekyll-gist (1.5.0) + octokit (~> 4.2) + jekyll-github-metadata (2.12.1) + jekyll (~> 3.4) + octokit (~> 4.0, != 4.4.0) + jekyll-mentions (1.4.1) + html-pipeline (~> 2.3) + jekyll (~> 3.0) + jekyll-optional-front-matter (0.3.0) + jekyll (~> 3.0) + jekyll-paginate (1.1.0) + jekyll-readme-index (0.2.0) + jekyll (~> 3.0) + jekyll-redirect-from (0.14.0) + jekyll (~> 3.3) + jekyll-relative-links (0.6.0) + jekyll (~> 3.3) + jekyll-remote-theme (0.3.1) + jekyll (~> 3.5) + rubyzip (>= 1.2.1, < 3.0) + jekyll-sass-converter (1.5.2) + sass (~> 3.4) + jekyll-seo-tag (2.5.0) + jekyll (~> 3.3) + jekyll-sitemap (1.2.0) + jekyll (~> 3.3) + jekyll-swiss (0.4.0) + jekyll-theme-architect (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-cayman (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-dinky (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-hacker (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-leap-day (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-merlot (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-midnight (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-minimal (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-modernist (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-primer (0.5.3) + jekyll (~> 3.5) + jekyll-github-metadata (~> 2.9) + jekyll-seo-tag (~> 2.0) + jekyll-theme-slate (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-tactile (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-theme-time-machine (0.1.1) + jekyll (~> 3.5) + jekyll-seo-tag (~> 2.0) + jekyll-titles-from-headings (0.5.1) + jekyll (~> 3.3) + jekyll-watch (2.2.1) + listen (~> 3.0) + jemoji (0.10.2) + gemoji (~> 3.0) + html-pipeline (~> 2.2) + jekyll (~> 3.0) + kramdown (1.17.0) + liquid (4.0.0) + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) + mercenary (0.3.6) + mini_portile2 (2.4.0) + minima (2.5.0) + jekyll (~> 3.5) + jekyll-feed (~> 0.9) + jekyll-seo-tag (~> 2.1) + minitest (5.11.3) + multipart-post (2.0.0) + nokogiri (1.10.2) + mini_portile2 (~> 2.4.0) + octokit (4.14.0) + sawyer (~> 0.8.0, >= 0.5.3) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (3.0.3) + rb-fsevent (0.10.3) + rb-inotify (0.10.0) + ffi (~> 1.0) + rouge (2.2.1) + ruby-enum (0.7.2) + i18n + ruby_dep (1.5.0) + rubyzip (1.2.2) + safe_yaml (1.0.5) + sass (3.7.3) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + sawyer (0.8.1) + addressable (>= 2.3.5, < 2.6) + faraday (~> 0.8, < 1.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + thread_safe (0.3.6) + typhoeus (1.3.1) + ethon (>= 0.9.0) + tzinfo (1.2.5) + thread_safe (~> 0.1) + unicode-display_width (1.5.0) + +PLATFORMS + ruby + +DEPENDENCIES + github-pages + +BUNDLED WITH + 2.0.1 diff --git a/docs/REFERENCE.md b/docs/REFERENCE.md index 2b939a14..05ebdd53 100644 --- a/docs/REFERENCE.md +++ b/docs/REFERENCE.md @@ -209,6 +209,13 @@ accessToken = index = * ONLY VALID WITH outputMode SPLUNKSTREAM * Splunk index to write events to. Defaults to main if none specified. + +extendIndexes = :,, + * Sample level setting. Use this setting enable eventgen to generate multi indexes for one sample. + * if you set the value with pattern like ":", it will treat as a prefix of an actual index, + * and is an integer that indicate the count of index you want to extend for this sample. + * eg: events from a sample with "extendIndexes = test_:5, main, web" setting will be added with indexes "test_0, test_1, + * test_2, test_3, test_4, main, web" randomly. source = * Valid with outputMode=modinput (default) & outputMode=splunkstream & outputMode=httpevent @@ -266,7 +273,7 @@ sampletype = raw | csv CSV allows you to override output fields for the sample like host, index, source and sourcetype from the CSV file. Will read the raw events from a field called _raw. Assumes the CSV file has a header row which defines field names. - OVERRIDES FOR DEFAULT FIELDS WILL ONLY WITH WITH outputMode SPLUNKSTREAM. + OVERRIDES FOR DEFAULT FIELDS WILL ONLY WORK WITH outputMode SPLUNKSTREAM. interval = * Only valid in mode = sample @@ -359,21 +366,21 @@ dayOfWeekRate = minuteOfHourRate = * Takes a JSON hash of 60 minutes of an hour, starting with 0 * Sample JSON: - { "0": 1, "2": 1...} + { "0": 1, "1": 1...} * If a match is not found, will default to count events * Also multiplied times dayOfWeekRate, hourOfDateRate, dayOfMonthRate, monthOfYearRate dayOfMonthRate = * Takes a JSON hash of 31 days of the month, starting with 1 * Sample JSON: - { "1": 1, "2": 1...} + { "1": 1, "1": 1...} * If a match is not found, will default to count events * Also multiplied times dayOfWeekRate, hourOfDateRate, minuteOfHourRate, monthOfYearRate monthOfYearRate = - * Takes a JSON hash of 60 minutes of an hour, starting with 0 + * Takes a JSON hash of 12 months of a year, starting with 1 * Sample JSON: - { "0": 1, "2": 1...} + { "1": 1, "2": 1...} * If a match is not found, will default to count events * Also multiplied times dayOfWeekRate, hourOfDateRate, minuteOfHourRate, dayOfMonthRate @@ -606,4 +613,4 @@ Note, "TARGET_NAME" is a variable that should be replaced by the hostname of Eve * Example: ``` $ curl http://localhost:9500/volume/egx1 -X POST -d '{"perDayVolume": 200}' - ``` \ No newline at end of file + ``` diff --git a/docs/SETUP.md b/docs/SETUP.md index 0558b6e6..6c50433c 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -1,4 +1,4 @@ -## Install ## +## Install There are multiple ways to use Eventgen, and you should choose the method that best fits your use case. Below are the two major ways to use Eventgen - as a PyPI module and as a Splunk App. Follow the instructions below depending on your ideal use: @@ -36,7 +36,7 @@ Below are the two major ways to use Eventgen - as a PyPI module and as a Splunk --- -## PyPI Installation / First Run ##### +## PyPI Installation / First Run To use Eventgen as a PyPI module, you need to either download/clone the source code or install direct from github. @@ -116,7 +116,7 @@ A quick preface on this mode of operation: due to its complexity, this is only r --- -## Splunk App Installation / First Run ##### +## Splunk App Installation / First Run To use Eventgen as a Splunk app, you need a SPL file. This SPL file can be obtained in one of two ways: 1. Through running the "build" process of the splunk_eventgen pypi module diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index a69ffe38..4e09f36f 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -1,14 +1,15 @@ # Eventgen * [Getting Started](SETUP.md) - * [Install](SETUP.md#install) - * [Configure](SETUP.md#configure) + * [Install](SETUP.md) + * [Configure](CONFIGURE.md) * [Tutorial](TUTORIAL.md) --- * [Basics](BASICS.md) * [Plugins](PLUGINS.md) * [Architecture](ARCHITECTURE.md) * [Performance](PERFORMANCE.md) +* [Contributing](CONTRIBUTE.md) --- * [Reference](REFERENCE.md) * [eventgen.conf.spec](REFERENCE.md#eventgenconfspec) diff --git a/docs/TUTORIAL.md b/docs/TUTORIAL.md index 4710a78e..d51c0d9b 100644 --- a/docs/TUTORIAL.md +++ b/docs/TUTORIAL.md @@ -2,10 +2,10 @@ The primary source of configuration done in Eventgen is governed by the `eventgen.conf` file. -* If deployed using containers, Eventgen will look for eventgen.conf in bundles under the `default` directory. For instance, if your bundle is named "datamix-app", you should archive your eventgen.conf in "datamix-app/default/eventgen.conf". -* If deployed as a Splunk App, Eventgen will look for eventgen.conf files for every app installed in Splunk, and will generate events for every eventgen.conf file it finds. This is convenient if you want to design event generation into a Technology Addon (TA) or other type of Splunk app. You can ship Eventgen configurations with your app and distribute the Eventgen app separately. +* If deployed using containers, Eventgen will look for `eventgen.conf` in bundles under the `default` directory. For instance, if your bundle is named `datamix-app`, you should archive your `eventgen.conf` in `datamix-app/default/eventgen.conf`. +* If deployed as a Splunk App, Eventgen will look for `eventgen.conf` files for every app installed in Splunk, and will generate events for every `eventgen.conf` file it finds. This is convenient if you want to design event generation into a Technology Addon (TA) or other type of Splunk app. You can ship Eventgen configurations with your app and distribute the Eventgen app separately. -The INI format of eventgen.conf can have one or more stanzas. Each stanza name is a sample file it will be reading from. There a number of options available in each stanza. For instance, breaking down this tutorial file option-by-option, we can see how this file will be used to set up Eventgen: +The INI format of `eventgen.conf` can have one or more stanzas. Each stanza name is a sample file it will be reading from. There a number of options available in each stanza. For instance, breaking down this tutorial file option-by-option, we can see how this file will be used to set up Eventgen: ``` [sample.tutorial1] @@ -66,6 +66,8 @@ There are various outputModes available (see the [spec](REFERENCE.md#eventgencon splunkPass = changeme ``` Parameters for setting up outputMode = splunkstream. This is only required if we want to run Eventgen outside of Splunk. As a Splunk App and running as a scripted input, eventgen will gather this information from Splunk itself. Since we'll be running this from the command line for the tutorial, please customize your username and password in the tutorial. +Note: +>When using outputMode=splunkstream for running Eventgen outside of Splunk, use parameter `PYTHONHTTPSVERIFY=0` to ignore the SSL error: `SSLError: [SSL: CERTIFICATE_VERIFY_FAILED]` ``` token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2},\d{3} diff --git a/docs/book.json b/docs/book.json deleted file mode 100644 index 39bf0c28..00000000 --- a/docs/book.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "title": "Eventgen Documentation", - "gitbook": "3.1.1", - "plugins": [ - "versions", - "expand-active-chapter", - "-sharing", - "fontsettings" - ], - "pluginsConfig": { - "fontsettings": { - "theme": "white", - "family": "sans", - "size": 1 - }, - "versions": { - "options": [ - { - "value": "http://go.sv.splunk.com/egdocs", - "text": "latest", - "selected": true - }, - { - "value": "http://go.sv.splunk.com/egdocs", - "text": "develop" - } - ] - } - } -} \ No newline at end of file diff --git a/docs/entrypoint.sh b/docs/entrypoint.sh deleted file mode 100755 index c5fbc0fb..00000000 --- a/docs/entrypoint.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -set -e - -if [ "$#" -eq "0" ]; then - cd /root/ - gitbook build - cd _book && python3 -m http.server 4000 -else - "$@" -fi diff --git a/docs/index.md b/docs/index.md index 4da11b23..bc7893f8 100644 --- a/docs/index.md +++ b/docs/index.md @@ -20,6 +20,7 @@ * [Basics](BASICS.md) * [Plugins](PLUGINS.md) * [Architecture](ARCHITECTURE.md) +* [Contribute](CONTRIBUTE.md) * [Performance](PERFORMANCE.md) * [Reference](REFERENCE.md) * [eventgen.conf.spec](REFERENCE.md#eventgenconfspec) diff --git a/setup.cfg b/setup.cfg index ab926b67..0a71e5d1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,12 +1,22 @@ [flake8] -exclude = .git,.tox,__pycache__,env,venv,build,dist,docs +exclude = .git,.tox,__pycache__,env,venv,splunk_eventgen/lib/concurrent,splunk_eventgen/lib/requests_futures max-line-length = 120 +ignore = E121,E123,E126,E226,E24,E704,W503,W504,E722,E731,W605 +# Includes default ignores, E722 (bare excepts), E731 (lambda usage), and W605 (escape sequences) [metadata] description-file = README.md version-from-file: __init__.py [yapf] -based_on_style = pep8 -spaces_before_comment = 4 -split_before_logical_operator = true +column_limit = 120 +split_all_comma_separated_values = false +split_before_named_assigns = false +split_before_first_argument = false +split_before_expression_after_opening_paren = false +split_before_closing_bracket = false +each_dict_entry_on_separate_line = false + +[isort] +# isort/yapf solutions to below files are not compatible +skip = splunk_eventgen/lib/concurrent,splunk_eventgen/lib/requests_futures \ No newline at end of file diff --git a/setup.py b/setup.py index 3df22c4a..c46fc7e7 100644 --- a/setup.py +++ b/setup.py @@ -1,17 +1,16 @@ #!/usr/bin/env python # encoding: utf-8 -from setuptools import setup -from setuptools import find_packages -import splunk_eventgen +from setuptools import find_packages, setup +import splunk_eventgen VERSION = splunk_eventgen.__version__ try: import pypandoc long_description = pypandoc.convert('README.md', 'rst') -except(IOError, ImportError): +except (IOError, ImportError): long_description = open('README.md').read() @@ -27,12 +26,9 @@ def readme(): long_description=long_description, author='Splunk, Inc.', classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: Software Development :: Build Tools', - 'Topic :: Software Development :: Testing', - 'Programming Language :: Python', + 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', + 'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: Software Development :: Build Tools', + 'Topic :: Software Development :: Testing', 'Programming Language :: Python', 'Programming Language :: Python :: 2.7'], keywords='splunk eventgen container containers docker automation', entry_points={'console_scripts': ["splunk_eventgen = splunk_eventgen.__main__:main"]}, @@ -55,6 +51,4 @@ def readme(): 'pyOpenSSL', 'flake8>=3.7.7', 'yapf>=0.26.0', - 'isort>=4.3.15' - ] - ) + 'isort>=4.3.15']) diff --git a/splunk_eventgen/__init__.py b/splunk_eventgen/__init__.py index 6bbcdcc3..04a51e0b 100644 --- a/splunk_eventgen/__init__.py +++ b/splunk_eventgen/__init__.py @@ -3,6 +3,7 @@ import json import os + file_location = os.path.normpath(os.path.realpath(__file__)) VERSION_FILE = "version.json" VERSION_LOCATION = os.path.normpath(os.path.join(file_location, '..', VERSION_FILE)) @@ -10,7 +11,7 @@ def _get_version(versionfile): """ - @param versionfile: File to get the version info from + @param versionfile: File to get the version info from @return: Version Number """ with open(VERSION_LOCATION, 'r') as fp: @@ -19,6 +20,7 @@ def _get_version(versionfile): fp.close() return version + def _set_dev_version(): """ Write .dev at the end of version @@ -33,6 +35,7 @@ def _set_dev_version(): fp.write(json.dumps(json_data)) fp.close() + def _set_release_version(): """ Remove .dev at end of version if it exists diff --git a/splunk_eventgen/__main__.py b/splunk_eventgen/__main__.py index c4c5d453..1dd058e9 100644 --- a/splunk_eventgen/__main__.py +++ b/splunk_eventgen/__main__.py @@ -6,6 +6,7 @@ import argparse import errno +import logging import os import shutil import sys @@ -16,61 +17,93 @@ FILE_LOCATION = os.path.dirname(os.path.abspath(__file__)) path_prepend = os.path.join(FILE_LOCATION, 'lib') sys.path.append(path_prepend) -import __init__ as splunk_eventgen_init -import logging -import eventgen_core + +import __init__ as splunk_eventgen_init # noqa isort:skip +import eventgen_core # noqa isort:skip EVENTGEN_VERSION = splunk_eventgen_init.__version__ logger = logging.getLogger() + def parse_args(): """Parse command line arguments""" subparser_dict = {} - parser = argparse.ArgumentParser(prog='Eventgen', - description='Splunk Event Generation Tool') + parser = argparse.ArgumentParser(prog='Eventgen', description='Splunk Event Generation Tool') parser.add_argument("-v", "--verbosity", action="count", help="increase output verbosity") parser.add_argument("--version", action='version', default=False, version='%(prog)s ' + EVENTGEN_VERSION) parser.add_argument("--modinput-mode", default=False) subparsers = parser.add_subparsers(title='commands', help="valid subcommands", dest='subcommand') # Generate subparser generate_subparser = subparsers.add_parser('generate', help="Generate events using a supplied config file") - generate_subparser.add_argument("configfile", help="Location of eventgen.conf, app folder, or name of an app in $SPLUNK_HOME/etc/apps to run") + generate_subparser.add_argument( + "configfile", help="Location of eventgen.conf, app folder, or name of an app in $SPLUNK_HOME/etc/apps to run") generate_subparser.add_argument("-s", "--sample", help="Run specified sample only, disabling all other samples") generate_subparser.add_argument("--keepoutput", action="store_true", help="Keep original outputMode for the sample") generate_subparser.add_argument("--devnull", action="store_true", help="Set outputMode to devnull") - generate_subparser.add_argument("--modinput", action="store_true", help="Set outputMode to modinput, to see metadata") + generate_subparser.add_argument("--modinput", action="store_true", + help="Set outputMode to modinput, to see metadata") generate_subparser.add_argument("-c", "--count", type=int, help="Set sample count") generate_subparser.add_argument("-i", "--interval", type=int, help="Set sample interval") - generate_subparser.add_argument("-b", "--backfill", help="Set time to backfill from. Note: to use it, send the parameter with space in front like ' -60m'") - generate_subparser.add_argument("-e", "--end", help="Set time to end generation at or a number of intervals to run. Note: to use it with a time, send the parameter with space in front like ' -10m'") + generate_subparser.add_argument("-b", "--backfill", help="Set time to backfill from") + generate_subparser.add_argument("-e", "--end", help="Set time to end generation at or a number of intervals to run") generate_subparser.add_argument("--generators", type=int, help="Number of GeneratorWorkers (mappers)") generate_subparser.add_argument("--outputters", type=int, help="Number of OutputWorkers (reducers)") generate_subparser.add_argument("--disableOutputQueue", action="store_true", help="Disable reducer step") - generate_subparser.add_argument("--multiprocess", action="store_true", help="Use multiprocesing instead of threading") + generate_subparser.add_argument("--multiprocess", action="store_true", + help="Use multiprocesing instead of threading") generate_subparser.add_argument("--profiler", action="store_true", help="Turn on cProfiler") generate_subparser.add_argument("--log-path", type=str, default="{0}/logs".format(FILE_LOCATION)) # Build subparser build_subparser = subparsers.add_parser('build', help="Will build different forms of sa-eventgen") - build_subparser.add_argument("--mode", type=str, default="splunk-app", help="Specify what type of package to build, defaults to splunk-app mode.") + build_subparser.add_argument("--mode", type=str, default="splunk-app", + help="Specify what type of package to build, defaults to splunk-app mode.") build_subparser.add_argument("--destination", help="Specify where to store the output of the build command.") - build_subparser.add_argument("--remove", default=True, help="Remove the build directory after completion. Defaults to True") + build_subparser.add_argument("--remove", default=True, + help="Remove the build directory after completion. Defaults to True") # WSGI subparser wsgi_subparser = subparsers.add_parser('wsgi', help="start a wsgi server to interact with eventgen.") - wsgi_subparser.add_argument("--daemon", action="store_true", help="Daemon will tell the wsgi server to start in a daemon mode and will release the cli.") + wsgi_subparser.add_argument( + "--daemon", action="store_true", + help="Daemon will tell the wsgi server to start in a daemon mode and will release the cli.") # Service subparser - service_subparser = subparsers.add_parser('service', help="Run Eventgen as a Nameko service. Parameters for starting this service can be defined as either environment variables or CLI arguments, where environment variables takes precedence. See help for more info.") - service_subparser.add_argument("--role", "-r", type=str, default=None, required=True, choices=["controller", "server"], help="Define the role for this Eventgen node. Options: master, slave") - service_subparser.add_argument("--amqp-uri", type=str, default=None, help="Full URI to AMQP endpoint in the format pyamqp://:@:. This can also be set using the environment variable EVENTGEN_AMQP_URI") - service_subparser.add_argument("--amqp-host", type=str, default=None, help="Specify AMQP hostname. This can also be set using the environment variable EVENTGEN_AMQP_HOST. Default is localhost") - service_subparser.add_argument("--amqp-port", type=int, default=None, help="Specify AMQP port. This can also be set using the environment variable EVENTGEN_AMQP_PORT. Default is 5672") - service_subparser.add_argument("--amqp-webport", type=int, default=None, help="Specify AMQP web port. This can also be set using the environment variable EVENTGEN_AMQP_WEBPORT. Default is 15672") - service_subparser.add_argument("--amqp-user", type=str, default=None, help="Specify AMQP user. This can also be set using the environment variable EVENTGEN_AMQP_USER. Default is 'guest'") - service_subparser.add_argument("--amqp-pass", type=str, default=None, help="Specify AMQP password. This can also be set using the environment variable EVENTGEN_AMQP_PASS. Default is 'guest'") - service_subparser.add_argument("--web-server-address", type=str, default=None, help="Specify nameko webserver address. This can also be set using the environment variable EVENTGEN_WEB_SERVER_ADDR. Default is 0.0.0.0:9500") + service_subparser = subparsers.add_parser( + 'service', + help=("Run Eventgen as a Nameko service. Parameters for starting this service can be defined as either env" + "variables or CLI arguments, where env variables takes precedence. See help for more info.")) + service_subparser.add_argument("--role", "-r", type=str, default=None, required=True, choices=[ + "controller", "server"], help="Define the role for this Eventgen node. Options: master, slave") + service_subparser.add_argument( + "--amqp-uri", type=str, default=None, + help=("Full URI to AMQP endpoint in the format pyamqp://:@:." + "This can also be set using the environment variable EVENTGEN_AMQP_URI")) + service_subparser.add_argument( + "--amqp-host", type=str, default=None, + help=("Specify AMQP hostname. This can also be set using the environment variable EVENTGEN_AMQP_HOST." + + "Default is localhost")) + service_subparser.add_argument( + "--amqp-port", type=int, default=None, + help=("Specify AMQP port. This can also be set using the environment variable EVENTGEN_AMQP_PORT." + + "Default is 5672")) + service_subparser.add_argument( + "--amqp-webport", type=int, default=None, + help=("Specify AMQP web port. This can also be set using the environment variable EVENTGEN_AMQP_WEBPORT." + + "Default is 15672")) + service_subparser.add_argument( + "--amqp-user", type=str, default=None, + help=("Specify AMQP user. This can also be set using the environment variable EVENTGEN_AMQP_USER." + + "Default is 'guest'")) + service_subparser.add_argument( + "--amqp-pass", type=str, default=None, + help=("Specify AMQP password. This can also be set using the environment variable EVENTGEN_AMQP_PASS." + + "Default is 'guest'")) + service_subparser.add_argument( + "--web-server-address", type=str, default=None, + help=("Specify nameko webserver address. This can also be set using the environment variable" + + "EVENTGEN_WEB_SERVER_ADDR. Default is 0.0.0.0:9500")) # Help subparser # NOTE: Keep this at the end so we can use the subparser_dict.keys() to display valid commands help_subparser = subparsers.add_parser('help', help="Display usage on a subcommand") - helpstr = "Help on a specific command, valid commands are: " + ", ".join(subparser_dict.keys() + ["help"]) + helpstr = "Help on a specific command, valid commands are: " + ", ".join(subparser_dict.keys() + ["help"]) help_subparser.add_argument("command", nargs='?', default="default", help=helpstr) # add subparsers to the subparser dict, this will be used later for usage / help statements. subparser_dict['generate'] = generate_subparser @@ -91,7 +124,7 @@ def parse_args(): if 'subcommand' not in args: parser.print_help() sys.exit(2) - + if args.subcommand == "service": if not args.role: msg = "Role is undefined. Please specify a role for this Eventgen service using --role/-r." @@ -120,10 +153,11 @@ def parse_args(): args.configfile = None return args + def wait_for_response(address, webport, timeout=300): ''' - This function extracts the hostname off the given address in the form ://:@: - and builds a URL in the form http://:. Using this URL, it tries to verify the endpoint is reachable. + Extracts the hostname off the given address in the form ://:@: and + builds a URL in the form http://:. Using this URL, it tries to verify the endpoint is reachable. Retry will occur for ~300s ''' @@ -133,12 +167,12 @@ def wait_for_response(address, webport, timeout=300): userid, password = creds.split(":") start = time.time() end = start - while end-start < timeout: + while end - start < timeout: try: r = requests.get("http://{}:{}".format(host, webport)) r.raise_for_status() return - except requests.exceptions.ConnectionError as e: + except requests.exceptions.ConnectionError: time.sleep(1) finally: end = time.time() @@ -146,6 +180,7 @@ def wait_for_response(address, webport, timeout=300): logger.exception(msg) raise Exception(msg) + def parse_cli_vars(config, args): config["AMQP_URI"] = args.amqp_uri if args.amqp_uri else config["AMQP_URI"] config["AMQP_HOST"] = args.amqp_host if args.amqp_host else config["AMQP_HOST"] @@ -156,6 +191,7 @@ def parse_cli_vars(config, args): config["WEB_SERVER_ADDRESS"] = args.web_server_address if args.web_server_address else config["WEB_SERVER_ADDRESS"] return config + def parse_env_vars(): osvars, config = dict(os.environ), {} config["AMQP_URI"] = osvars.get("EVENTGEN_AMQP_URI", None) @@ -167,6 +203,7 @@ def parse_env_vars(): config["WEB_SERVER_ADDRESS"] = osvars.get("EVENTGEN_WEB_SERVER_ADDR", "0.0.0.0:9500") return config + def rectify_config(config): # For nameko purposes, all we need to pass into the config is AMQP_URI and WEB_SERVER_ADDRESS. new = {} @@ -176,22 +213,21 @@ def rectify_config(config): new["AMQP_URI"] = config["AMQP_URI"] else: if all([config["AMQP_HOST"], config["AMQP_PORT"], config["AMQP_USER"], config["AMQP_PASS"]]): - new["AMQP_URI"] = "pyamqp://{user}:{pw}@{host}:{port}".format(user=config["AMQP_USER"], - pw=config["AMQP_PASS"], - host=config["AMQP_HOST"], - port=config["AMQP_PORT"]) + new["AMQP_URI"] = "pyamqp://{user}:{pw}@{host}:{port}".format( + user=config["AMQP_USER"], pw=config["AMQP_PASS"], host=config["AMQP_HOST"], port=config["AMQP_PORT"]) else: msg = "AMQP_URI is not defined and cannot be constructed. Check environment variables/CLI arguments." logger.exception(msg) raise Exception(msg) return new + def run_nameko(args): # Running nameko imports here so that Eventgen as a module does not require nameko to run. import eventlet eventlet.monkey_patch() from nameko.runners import ServiceRunner - # In order to make this run locally as well as within a container-ized environment, we're to pull variables + # In order to make this run locally as well as within a container-ized environment, we're to pull variables # from both environment variables and CLI arguments, where CLI will take precendence. config = parse_env_vars() config = parse_cli_vars(config, args) @@ -229,6 +265,7 @@ def run_nameko(args): # runner.wait completed break + def exclude_function(filename): # removing any hidden . files. last_index = filename.rfind('/') @@ -240,13 +277,15 @@ def exclude_function(filename): else: return False + def make_tarfile(output_filename, source_dir): import tarfile with tarfile.open(output_filename, "w:gz") as tar: tar.add(source_dir, arcname=os.path.basename(source_dir), exclude=exclude_function) + def build_splunk_app(dest, source=os.getcwd(), remove=True): - import errno, imp + import imp cwd = os.getcwd() os.chdir(source) directory = os.path.join(dest, 'SA-Eventgen') @@ -275,6 +314,7 @@ def build_splunk_app(dest, source=os.getcwd(), remove=True): shutil.rmtree(directory) os.chdir(cwd) + def convert_verbosity_count_to_logging_level(verbosity): if verbosity == 0: return logging.ERROR @@ -285,6 +325,7 @@ def convert_verbosity_count_to_logging_level(verbosity): else: return logging.ERROR + def main(): cwd = os.getcwd() args = parse_args() diff --git a/splunk_eventgen/eventgen_core.py b/splunk_eventgen/eventgen_core.py index e9db47f6..71c80647 100644 --- a/splunk_eventgen/eventgen_core.py +++ b/splunk_eventgen/eventgen_core.py @@ -1,17 +1,19 @@ #!/usr/bin/env python # encoding: utf-8 -from lib.eventgenconfig import Config -from lib.eventgentimer import Timer -from lib.eventgenexceptions import PluginNotLoaded, FailedLoadingPlugin -from lib.outputcounter import OutputCounter +import imp +import json import logging import logging.config import os import sys -import imp -from Queue import Queue, Empty -from threading import Thread import time +from Queue import Empty, Queue +from threading import Thread + +from lib.eventgenconfig import Config +from lib.eventgenexceptions import PluginNotLoaded +from lib.eventgentimer import Timer +from lib.outputcounter import OutputCounter lib_path_prepend = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'lib') sys.path.insert(0, lib_path_prepend) @@ -26,23 +28,24 @@ import logutils import logutils.queue -file_path=os.path.dirname(os.path.realpath(__file__)) +file_path = os.path.dirname(os.path.realpath(__file__)) EVENTGEN_DIR = os.path.realpath(os.path.join(file_path, "..")) EVENTGEN_ENGINE_CONF_PATH = os.path.abspath(os.path.join(file_path, "default", "eventgen_engine.conf")) -import json + class JSONFormatter(logging.Formatter): """ Quick and dirty formatter that turns the log into a quick json format """ + def format(self, record): message = record.msg if not isinstance(message, dict): - #The record is probably a string + # The record is probably a string try: message = json.loads(message) except ValueError: - #Abort, just store the message as an attribute + # Abort, just store the message as an attribute message = {"message": message} if "timestamp" not in message: @@ -51,8 +54,9 @@ def format(self, record): message["level"] = logging.getLevelName(record.levelno) return json.dumps(message) + class EventGenerator(object): - def __init__(self, args=None ): + def __init__(self, args=None): ''' This object will allow you to generate and control eventgen. It should be handed the parse_args object from __main__ and will hand the argument object to the config parser of eventgen5. This will provide the @@ -81,12 +85,11 @@ def _load_config(self, configfile, **kwargs): :param configfile: :return: ''' - #TODO: The old eventgen had strange cli args, and usage of args. We should probably update the module args - #to match more of what this is doing... - new_args={} + # TODO: The old eventgen had strange cli args. We should probably update the module args to match this usage. + new_args = {} if "args" in kwargs: args = kwargs["args"] - outputer = [key for key in ["keepoutput","devnull","modinput"] if getattr(args, key)] + outputer = [key for key in ["keepoutput", "devnull", "modinput"] if getattr(args, key)] if len(outputer) > 0: new_args["override_outputter"] = outputer[0] if getattr(args, "count"): @@ -112,7 +115,7 @@ def _load_config(self, configfile, **kwargs): self.config = Config(configfile, **new_args) self.config.parse() self._reload_plugins() - #TODO: Probably should destroy pools better so processes are cleaned. + # TODO: Probably should destroy pools better so processes are cleaned. self._setup_pools() def _reload_plugins(self): @@ -120,11 +123,14 @@ def _reload_plugins(self): # Plugins must be loaded before objects that do work, otherwise threads and processes generated will not have # the modules loaded in active memory. try: - self.config.outputPlugins = { } - plugins = self._initializePlugins(os.path.join(file_path, 'lib', 'plugins', 'output'), self.config.outputPlugins, 'output') + self.config.outputPlugins = {} + plugins = self._initializePlugins( + os.path.join(file_path, 'lib', 'plugins', 'output'), self.config.outputPlugins, 'output') self.config.validOutputModes.extend(plugins) - self._initializePlugins(os.path.join(file_path, 'lib', 'plugins', 'generator'), self.config.plugins, 'generator') - plugins = self._initializePlugins(os.path.join(file_path, 'lib', 'plugins', 'rater'), self.config.plugins, 'rater') + self._initializePlugins( + os.path.join(file_path, 'lib', 'plugins', 'generator'), self.config.plugins, 'generator') + plugins = self._initializePlugins( + os.path.join(file_path, 'lib', 'plugins', 'rater'), self.config.plugins, 'rater') self.config._complexSettings['rater'] = plugins except Exception as e: self.logger.exception(e) @@ -133,13 +139,12 @@ def _load_custom_plugins(self, PluginNotLoadedException): plugintype = PluginNotLoadedException.type plugin = PluginNotLoadedException.name bindir = PluginNotLoadedException.bindir - libdir = PluginNotLoadedException.libdir plugindir = PluginNotLoadedException.plugindir pluginsdict = self.config.plugins if plugintype in ('generator', 'rater') else self.config.outputPlugins - #APPPERF-263: be picky when loading from an app bindir (only load name) + # APPPERF-263: be picky when loading from an app bindir (only load name) self._initializePlugins(bindir, pluginsdict, plugintype, name=plugin) - #APPPERF-263: be greedy when scanning plugin dir (eat all the pys) + # APPPERF-263: be greedy when scanning plugin dir (eat all the pys) self._initializePlugins(plugindir, pluginsdict, plugintype) def _setup_pools(self): @@ -165,31 +170,33 @@ def _create_timer_threadpool(self, threadcount=100): self.sampleQueue = Queue(maxsize=0) num_threads = threadcount for i in range(num_threads): - worker = Thread(target=self._worker_do_work, - args=(self.sampleQueue, self.loggingQueue, ), - name="TimeThread{0}".format(i)) + worker = Thread(target=self._worker_do_work, args=( + self.sampleQueue, + self.loggingQueue, + ), name="TimeThread{0}".format(i)) worker.setDaemon(True) worker.start() def _create_output_threadpool(self, threadcount=1): ''' the output thread pool is used for output plugins that need to control file locking, or only have 1 set thread - to send all the data out of. this FIFO queue just helps make sure there are file collisions or write collisions. + to send all the data out of. This FIFO queue just helps make sure there are file collisions or write collisions. There's only 1 active thread for this queue, if you're ever considering upping this, don't. Just shut off the outputQueue and let each generator directly output it's data. :param threadcount: is how many active output threads we want to allow inside of eventgen. Default 1 :return: ''' - #TODO: Make this take the config param and figure out what we want to do with this. + # TODO: Make this take the config param and figure out what we want to do with this. if getattr(self, "manager", None): self.outputQueue = self.manager.Queue(maxsize=500) else: self.outputQueue = Queue(maxsize=500) num_threads = threadcount for i in range(num_threads): - worker = Thread(target=self._worker_do_work, - args=(self.outputQueue, self.loggingQueue, ), - name="OutputThread{0}".format(i)) + worker = Thread(target=self._worker_do_work, args=( + self.outputQueue, + self.loggingQueue, + ), name="OutputThread{0}".format(i)) worker.setDaemon(True) worker.start() @@ -206,7 +213,7 @@ def _create_generator_pool(self, workercount=20): import multiprocessing self.manager = multiprocessing.Manager() self.loggingQueue = self.manager.Queue() - self.logging_pool = Thread(target=self.logger_thread, args=(self.loggingQueue,), name="LoggerThread") + self.logging_pool = Thread(target=self.logger_thread, args=(self.loggingQueue, ), name="LoggerThread") self.logging_pool.start() # since we're now in multiprocess, we need to use better queues. self.workerQueue = multiprocessing.JoinableQueue(maxsize=500) @@ -220,7 +227,8 @@ def _create_generator_pool(self, workercount=20): for i in range(workercount): self.output_counters.append(OutputCounter()) for i in range(worker_threads): - worker = Thread(target=self._generator_do_work, args=(self.workerQueue, self.loggingQueue, self.output_counters[i])) + worker = Thread(target=self._generator_do_work, args=(self.workerQueue, self.loggingQueue, + self.output_counters[i])) worker.setDaemon(True) worker.start() else: @@ -234,9 +242,12 @@ def _create_generator_workers(self, workercount=20): import multiprocessing self.workerPool = [] for worker in xrange(workercount): - #builds a list of tuples to use the map function - process = multiprocessing.Process(target=self._proc_worker_do_work, - args=(self.workerQueue, self.loggingQueue, self.genconfig, )) + # builds a list of tuples to use the map function + process = multiprocessing.Process(target=self._proc_worker_do_work, args=( + self.workerQueue, + self.loggingQueue, + self.genconfig, + )) self.workerPool.append(process) process.start() else: @@ -262,23 +273,28 @@ def _setup_loggers(self, args=None, config=None): console_handler.setFormatter(detailed_formatter) console_handler.setLevel(logging.DEBUG) - file_handler = logging.handlers.RotatingFileHandler(eventgen_main_logger_path, maxBytes=2500000, backupCount=20) + file_handler = logging.handlers.RotatingFileHandler(eventgen_main_logger_path, maxBytes=2500000, + backupCount=20) file_handler.setFormatter(detailed_formatter) file_handler.setLevel(logging.DEBUG) - eventgen_controller_file_handler = logging.handlers.RotatingFileHandler(eventgen_controller_logger_path, maxBytes=2500000, backupCount=20) + eventgen_controller_file_handler = logging.handlers.RotatingFileHandler(eventgen_controller_logger_path, + maxBytes=2500000, backupCount=20) eventgen_controller_file_handler.setFormatter(detailed_formatter) eventgen_controller_file_handler.setLevel(logging.DEBUG) - error_file_handler = logging.handlers.RotatingFileHandler(eventgen_error_logger_path, maxBytes=2500000, backupCount=20) + error_file_handler = logging.handlers.RotatingFileHandler(eventgen_error_logger_path, maxBytes=2500000, + backupCount=20) error_file_handler.setFormatter(detailed_formatter) error_file_handler.setLevel(logging.ERROR) - metrics_file_handler = logging.handlers.RotatingFileHandler(eventgen_metrics_logger_path, maxBytes=2500000, backupCount=20) + metrics_file_handler = logging.handlers.RotatingFileHandler(eventgen_metrics_logger_path, maxBytes=2500000, + backupCount=20) metrics_file_handler.setFormatter(json_formatter) metrics_file_handler.setLevel(logging.INFO) - server_file_handler = logging.handlers.RotatingFileHandler(eventgen_server_logger_path, maxBytes=2500000, backupCount=10) + server_file_handler = logging.handlers.RotatingFileHandler(eventgen_server_logger_path, maxBytes=2500000, + backupCount=10) server_file_handler.setFormatter(json_formatter) server_file_handler.setLevel(logging.INFO) @@ -321,10 +337,12 @@ def _setup_loggers(self, args=None, config=None): # We need to have debugv from the olderversions of eventgen. DEBUG_LEVELV_NUM = 9 logging.addLevelName(DEBUG_LEVELV_NUM, "DEBUGV") + def debugv(self, message, *args, **kws): # Yes, logger takes its '*args' as 'args'. if self.isEnabledFor(DEBUG_LEVELV_NUM): self._log(DEBUG_LEVELV_NUM, message, args, **kws) + logging.Logger.debugv = debugv self.logger = logging.getLogger('eventgen') self.loggingQueue = None @@ -344,6 +362,7 @@ def _worker_do_work(self, work_queue, logging_queue): except Exception as e: self.logger.exception(e) raise e + def _generator_do_work(self, work_queue, logging_queue, output_counter=None): while not self.stopping: try: @@ -408,13 +427,13 @@ def _initializePlugins(self, dirname, plugins, plugintype, name=None): syspathset = set(sys.path) dirname = os.path.abspath(dirname) - self.logger.debugv("looking for plugin(s) in {}".format(dirname)) + self.logger.debug("looking for plugin(s) in {}".format(dirname)) if not os.path.isdir(dirname): - self.logger.debugv("directory {} does not exist ... moving on".format(dirname)) + self.logger.debug("directory {} does not exist ... moving on".format(dirname)) return ret # Include all plugin directories in sys.path for includes - if not dirname in sys.path: + if dirname not in sys.path: syspathset.add(dirname) sys.path = list(syspathset) @@ -429,16 +448,16 @@ def _initializePlugins(self, dirname, plugins, plugintype, name=None): base, extension = os.path.splitext(basename) # If we're a python file and we don't start with _ - #if extension == ".py" and not basename.startswith("_"): + # if extension == ".py" and not basename.startswith("_"): # APPPERF-263: If name param is supplied, only attempt to load # {name}.py from {app}/bin directory if extension == ".py" and ((name is None and not basename.startswith("_")) or base == name): - self.logger.debugv("Searching for plugin in file '%s'" % filename) + self.logger.debug("Searching for plugin in file '%s'" % filename) try: # Import the module - #module = imp.load_source(base, filename) + # module = imp.load_source(base, filename) mod_name, mod_path, mod_desc = imp.find_module(base, [dirname]) - #TODO: Probably need to adjust module.load() to be added later so this can be pickled. + # TODO: Probably need to adjust module.load() to be added later so this can be pickled. module = imp.load_module(base, mod_name, mod_path, mod_desc) plugin = module.load() @@ -487,33 +506,36 @@ def start(self, join_after_start=True): self.logger.info("No samples found. Exiting.") for s in self.config.samples: if s.interval > 0 or s.mode == 'replay' or s.end != "0": - self.logger.info("Creating timer object for sample '%s' in app '%s'" % (s.name, s.app) ) + self.logger.info("Creating timer object for sample '%s' in app '%s'" % (s.name, s.app)) # This is where the timer is finally sent to a queue to be processed. Needs to move to this object. try: - t = Timer(1.0, sample=s, config=self.config, - genqueue=self.workerQueue, outputqueue=self.outputQueue, loggingqueue=self.loggingQueue) + t = Timer(1.0, sample=s, config=self.config, genqueue=self.workerQueue, + outputqueue=self.outputQueue, loggingqueue=self.loggingQueue) except PluginNotLoaded as pnl: self._load_custom_plugins(pnl) - t = Timer(1.0, sample=s, config=self.config, - genqueue=self.workerQueue, outputqueue=self.outputQueue, loggingqueue=self.loggingQueue) + t = Timer(1.0, sample=s, config=self.config, genqueue=self.workerQueue, + outputqueue=self.outputQueue, loggingqueue=self.loggingQueue) except Exception as e: raise e self.sampleQueue.put(t) if join_after_start: self.logger.info("All timers started, joining queue until it's empty.") self.join_process() - ## Only need to start timers once + # Only need to start timers once # Every 5 seconds, get values and output basic statistics about our operations - #TODO: Figure out how to do this better... - #generatorsPerSec = (generatorDecrements - generatorQueueCounter) / 5 - #outputtersPerSec = (outputDecrements - outputQueueCounter) / 5 - #outputQueueCounter = outputDecrements - #generatorQueueCounter = generatorDecrements - #self.logger.info('OutputQueueDepth=%d GeneratorQueueDepth=%d GeneratorsPerSec=%d OutputtersPerSec=%d' % (self.config.outputQueueSize.value(), self.config.generatorQueueSize.value(), generatorsPerSec, outputtersPerSec)) - #kiloBytesPerSec = self.config.bytesSent.valueAndClear() / 5 / 1024 - #gbPerDay = (kiloBytesPerSec / 1024 / 1024) * 60 * 60 * 24 - #eventsPerSec = self.config.eventsSent.valueAndClear() / 5 - #self.logger.info('GlobalEventsPerSec=%s KilobytesPerSec=%1f GigabytesPerDay=%1f' % (eventsPerSec, kiloBytesPerSec, gbPerDay)) + # TODO: Figure out how to do this better... + # generatorsPerSec = (generatorDecrements - generatorQueueCounter) / 5 + # outputtersPerSec = (outputDecrements - outputQueueCounter) / 5 + # outputQueueCounter = outputDecrements + # generatorQueueCounter = generatorDecrements + # self.logger.info('OutputQueueDepth=%d GeneratorQueueDepth=%d GeneratorsPerSec=%d OutputtersPerSec=%d' % + # (self.config.outputQueueSize.value(), self.config.generatorQueueSize.value(), + # generatorsPerSec, outputtersPerSec)) + # kiloBytesPerSec = self.config.bytesSent.valueAndClear() / 5 / 1024 + # gbPerDay = (kiloBytesPerSec / 1024 / 1024) * 60 * 60 * 24 + # eventsPerSec = self.config.eventsSent.valueAndClear() / 5 + # self.logger.info('GlobalEventsPerSec=%s KilobytesPerSec=%1f GigabytesPerDay=%1f' % + # (eventsPerSec, kiloBytesPerSec, gbPerDay)) def join_process(self): ''' @@ -522,7 +544,8 @@ def join_process(self): :return: ''' try: - while not self.sampleQueue.empty() or self.sampleQueue.unfinished_tasks > 0 or not self.workerQueue.empty() or self.workerQueue.unfinished_tasks > 0: + while not self.sampleQueue.empty() or self.sampleQueue.unfinished_tasks > 0 or not self.workerQueue.empty( + ) or self.workerQueue.unfinished_tasks > 0: time.sleep(5) self.logger.info("All timers have finished, signalling workers to exit.") self.stop() @@ -538,13 +561,13 @@ def stop(self): self.logger.info("All timers exited, joining generation queue until it's empty.") self.workerQueue.join() - # if we're in multiprocess, make sure that since all the timers stopped, we don't let any more generators get added. + # if we're in multiprocess, make sure we don't add more generators after the timers stopped. if self.args.multiprocess: self.genconfig["stopping"] = True for worker in self.workerPool: count = 0 # We wait for a minute until terminating the worker - while worker.exitcode == None and count != 20: + while worker.exitcode is None and count != 20: if count == 30: self.logger.info("Terminating worker {0}".format(worker._name)) worker.terminate() @@ -586,4 +609,3 @@ def check_running(self): else: return True return False - diff --git a/splunk_eventgen/eventgen_nameko_controller.py b/splunk_eventgen/eventgen_nameko_controller.py index 12cda2e7..52192859 100644 --- a/splunk_eventgen/eventgen_nameko_controller.py +++ b/splunk_eventgen/eventgen_nameko_controller.py @@ -1,22 +1,26 @@ -from nameko.rpc import rpc -from nameko.events import EventDispatcher, event_handler, BROADCAST -from nameko.web.handlers import http -from pyrabbit.api import Client import atexit +import json import logging import os import socket -from logger.logger_config import controller_logger_config import time -import json + +from pyrabbit.api import Client + +from logger.logger_config import controller_logger_config +from nameko.events import BROADCAST, EventDispatcher, event_handler +from nameko.rpc import rpc +from nameko.web.handlers import http FILE_PATH = os.path.dirname(os.path.realpath(__file__)) EVENTGEN_ENGINE_CONF_PATH = os.path.abspath(os.path.join(FILE_PATH, "default", "eventgen_engine.conf")) + def exit_handler(client, hostname, logger): client.delete_vhost(hostname) logger.info("Deleted vhost {}. Shutting down.".format(hostname)) + class EventgenController(object): name = "eventgen_controller" @@ -38,17 +42,14 @@ class EventgenController(object): config["AMQP_PASS"] = osvars.get("EVENTGEN_AMQP_PASS", "guest") pyrabbit_cl = Client('{0}:{1}'.format(config['AMQP_HOST'], config['AMQP_WEBPORT']), - '{0}'.format(config['AMQP_USER']), - '{0}'.format(config['AMQP_PASS'])) + '{0}'.format(config['AMQP_USER']), '{0}'.format(config['AMQP_PASS'])) pyrabbit_cl.create_vhost(host) log.info("Vhost set to {}".format(host)) log.info("Current Vhosts are {}".format(pyrabbit_cl.get_vhost_names())) atexit.register(exit_handler, client=pyrabbit_cl, hostname=host, logger=log) - ############################################## - ################ RPC Methods ################# - ############################################## + # RPC Methods @event_handler("eventgen_server", "server_status", handler_type=BROADCAST, reliable_delivery=False) def event_handler_server_status(self, payload): @@ -188,7 +189,7 @@ def bundle(self, target, data): except Exception as e: self.log.exception(e) return "500", "Exception: {}".format(e.message) - + @rpc def setup(self, target, data): try: @@ -210,7 +211,7 @@ def get_volume(self, target): except Exception as e: self.log.exception(e) return "500", "Exception: {}".format(e.message) - + @rpc def set_volume(self, target, data): try: @@ -238,10 +239,7 @@ def reset(self, target): self.log.exception(e) return '500', "Exception: {}".format(e.message) - - ############################################## - ################ HTTP Methods ################ - ############################################## + # HTTP Methods @http('GET', '/') def root_page(self, request): @@ -439,15 +437,13 @@ def http_set_volume_target(self, request, target="all"): def http_reset(self, request): return self.reset(target="all") - ############################################## - ############### Helper Methods ############### - ############################################## + # Helper Methods def receive_status(self, data): if data['server_name'] and data['server_status']: self.server_status[data['server_name']] = data['server_status'] rec_time = time.time() - self.log.info("receive {}'s status, update the status at time:{}".format(data['server_name'],rec_time)) + self.log.info("receive {}'s status, update the status at time:{}".format(data['server_name'], rec_time)) self.server_status['time'] = rec_time def receive_conf(self, data): @@ -461,14 +457,15 @@ def receive_volume(self, data): def process_server_status(self, current_time, num_retries=15, delay=0.3): current_server_vhosts = self.get_current_server_vhosts() server_time = self.server_status['time'] if 'time' in self.server_status else 0 - server_vhost_len = len(self.server_status) if 'time' not in self.server_status else len(self.server_status)-1 + server_vhost_len = len(self.server_status) if 'time' not in self.server_status else len(self.server_status) - 1 if current_server_vhosts: for i in range(num_retries): if server_vhost_len != len(current_server_vhosts) or server_time < current_time: time.sleep(delay) current_server_vhosts = self.get_current_server_vhosts() server_time = self.server_status['time'] if 'time' in self.server_status else 0 - server_vhost_len = len(self.server_status) if 'time' not in self.server_status else len(self.server_status)-1 + server_vhost_len = len( + self.server_status) if 'time' not in self.server_status else len(self.server_status) - 1 else: break dump_value = self.calculate_throughput(self.server_status) @@ -515,10 +512,7 @@ def check_vhost(self, vhost_name): return False def calculate_throughput(self, data): - throughput_summary = { 'TOTAL_VOLUME_MB': 0, - 'TOTAL_COUNT': 0, - 'THROUGHPUT_VOLUME_KB': 0, - 'THROUGHPUT_COUNT': 0} + throughput_summary = {'TOTAL_VOLUME_MB': 0, 'TOTAL_COUNT': 0, 'THROUGHPUT_VOLUME_KB': 0, 'THROUGHPUT_COUNT': 0} for server_name, server_status in data.items(): if server_name != 'time' and 'THROUGHPUT_STATUS' in server_status: server_throughput = server_status['THROUGHPUT_STATUS'] diff --git a/splunk_eventgen/eventgen_nameko_dependency.py b/splunk_eventgen/eventgen_nameko_dependency.py index a22577c9..6bbcd54e 100644 --- a/splunk_eventgen/eventgen_nameko_dependency.py +++ b/splunk_eventgen/eventgen_nameko_dependency.py @@ -1,9 +1,11 @@ -from nameko.extensions import DependencyProvider -import eventgen_core -import logging import argparse -import sys +import logging import os +import sys + +import eventgen_core +from nameko.extensions import DependencyProvider + FILE_PATH = os.path.dirname(os.path.realpath(__file__)) CUSTOM_CONFIG_PATH = os.path.realpath(os.path.join(FILE_PATH, "default", "eventgen_wsgi.conf")) @@ -12,6 +14,7 @@ # eventgen_nameko_dependency: error: unrecognized arguments: --role master --config server_conf.yml sys.argv = [sys.argv.pop(0)] + def create_args(): parser = argparse.ArgumentParser(prog="eventgen_nameko_dependency") args = parser.parse_args() @@ -38,6 +41,7 @@ def create_args(): args.modinput_mode = False return args + class EventgenDependency(DependencyProvider): arguments = create_args() diff --git a/splunk_eventgen/eventgen_nameko_server.py b/splunk_eventgen/eventgen_nameko_server.py index 4bb89e50..cdfe2f35 100644 --- a/splunk_eventgen/eventgen_nameko_server.py +++ b/splunk_eventgen/eventgen_nameko_server.py @@ -1,21 +1,23 @@ -from nameko.rpc import rpc -from nameko.web.handlers import http -from nameko.events import EventDispatcher, event_handler, BROADCAST -from pyrabbit.api import Client import atexit import ConfigParser -import yaml +import glob import json +import logging import os +import shutil import socket -import time -import requests -import glob import tarfile +import time import zipfile -import shutil + +import requests +import yaml +from pyrabbit.api import Client + import eventgen_nameko_dependency -import logging +from nameko.events import BROADCAST, EventDispatcher, event_handler +from nameko.rpc import rpc +from nameko.web.handlers import http FILE_PATH = os.path.dirname(os.path.realpath(__file__)) EVENTGEN_DIR = os.path.realpath(os.path.join(FILE_PATH, "..")) @@ -27,7 +29,6 @@ def get_eventgen_name_from_conf(): with open(os.path.abspath(os.path.join(FILE_PATH, "server_conf.yml"))) as config_yml: loaded_yml = yaml.load(config_yml) return loaded_yml['EVENTGEN_NAME'] if 'EVENTGEN_NAME' in loaded_yml else socket.gethostname() - return None def exit_handler(client, hostname, logger): @@ -53,8 +54,7 @@ class EventgenServer(object): config["AMQP_PASS"] = osvars.get("EVENTGEN_AMQP_PASS", "guest") pyrabbit_cl = Client('{0}:{1}'.format(config['AMQP_HOST'], config['AMQP_WEBPORT']), - '{0}'.format(config['AMQP_USER']), - '{0}'.format(config['AMQP_PASS'])) + '{0}'.format(config['AMQP_USER']), '{0}'.format(config['AMQP_PASS'])) pyrabbit_cl.create_vhost(host) log.info("Vhost set to {}".format(host)) @@ -85,7 +85,7 @@ def get_status(self): if self.eventgen_dependency.eventgen.check_running(): # running status = 1 - elif self.eventgen_dependency.eventgen.completed == True: + elif self.eventgen_dependency.eventgen.completed is True: # all samples completed and stop status = 2 else: @@ -96,9 +96,10 @@ def get_status(self): res["CONFIGURED"] = self.eventgen_dependency.configured res["CONFIG_FILE"] = self.eventgen_dependency.configfile res["TOTAL_VOLUME"] = self.total_volume - res["QUEUE_STATUS"] = {'SAMPLE_QUEUE': {'UNFINISHED_TASK': 'N/A', 'QUEUE_LENGTH': 'N/A'}, - 'OUTPUT_QUEUE': {'UNFINISHED_TASK': 'N/A', 'QUEUE_LENGTH': 'N/A'}, - 'WORKER_QUEUE': {'UNFINISHED_TASK': 'N/A', 'QUEUE_LENGTH': 'N/A'}} + res["QUEUE_STATUS"] = { + 'SAMPLE_QUEUE': {'UNFINISHED_TASK': 'N/A', 'QUEUE_LENGTH': 'N/A'}, 'OUTPUT_QUEUE': { + 'UNFINISHED_TASK': 'N/A', 'QUEUE_LENGTH': 'N/A'}, 'WORKER_QUEUE': { + 'UNFINISHED_TASK': 'N/A', 'QUEUE_LENGTH': 'N/A'}} res['THROUGHPUT_STATUS'] = self.get_throughput() if hasattr(self.eventgen_dependency.eventgen, "sampleQueue"): res["QUEUE_STATUS"]['SAMPLE_QUEUE'][ @@ -114,9 +115,7 @@ def get_status(self): res["QUEUE_STATUS"]['WORKER_QUEUE']['QUEUE_LENGTH'] = self.eventgen_dependency.eventgen.workerQueue.qsize() return res - ############################################## - ############### Real Methods ################# - ############################################## + # Real Methods def index(self): self.log.info("index method called") @@ -139,14 +138,8 @@ def index(self): sample_queue_status = status["QUEUE_STATUS"]["SAMPLE_QUEUE"] output_queue_status = status["QUEUE_STATUS"]["OUTPUT_QUEUE"] - return home_page.format(host, - eventgen_status, - configured, - config_file, - total_volume, - worker_queue_status, - sample_queue_status, - output_queue_status) + return home_page.format(host, eventgen_status, configured, config_file, total_volume, worker_queue_status, + sample_queue_status, output_queue_status) def status(self): self.log.info('Status method called.') @@ -344,28 +337,18 @@ def setup(self, data): new_key = bool(data.get("new_key", True)) def create_new_hec_key(hostname): - requests.post("https://{0}:{1}/servicesNS/admin/splunk_httpinput/data/inputs/http/http".format( - hostname, mgmt_port), - auth=("admin", password), - data={"disabled": "0"}, - verify=False) + requests.post( + "https://{0}:{1}/servicesNS/admin/splunk_httpinput/data/inputs/http/http".format( + hostname, mgmt_port), auth=("admin", password), data={"disabled": "0"}, verify=False) requests.delete( - "https://{0}:{1}/servicesNS/admin/splunk_httpinput/data/inputs/http/{2}".format( - hostname, mgmt_port,key_name), - verify=False, - auth=("admin", password) - ) + "https://{0}:{1}/servicesNS/admin/splunk_httpinput/data/inputs/http/{2}".format( + hostname, mgmt_port, key_name), verify=False, auth=("admin", password)) requests.post( - "https://{0}:{1}/servicesNS/admin/splunk_httpinput/data/inputs/http?output_mode=json".format( - hostname, mgmt_port), - verify=False, - auth=("admin", password), - data={"name": key_name}) + "https://{0}:{1}/servicesNS/admin/splunk_httpinput/data/inputs/http?output_mode=json".format( + hostname, mgmt_port), verify=False, auth=("admin", password), data={"name": key_name}) r = requests.post( - "https://{0}:{1}/servicesNS/admin/splunk_httpinput/data/inputs/http/{2}?output_mode=json".format( - hostname, mgmt_port, key_name), - verify=False, - auth=("admin", password)) + "https://{0}:{1}/servicesNS/admin/splunk_httpinput/data/inputs/http/{2}?output_mode=json".format( + hostname, mgmt_port, key_name), verify=False, auth=("admin", password)) return str(json.loads(r.text)["entry"][0]["content"]["token"]) self.discovered_servers = [] @@ -375,10 +358,9 @@ def create_new_hec_key(hostname): if new_key: key = create_new_hec_key(formatted_hostname) - self.discovered_servers.append({"protocol": str(protocol), - "address": str(formatted_hostname), - "port": str(hec_port), - "key": str(key)}) + self.discovered_servers.append({ + "protocol": str(protocol), "address": str(formatted_hostname), "port": str(hec_port), "key": + str(key)}) except socket.gaierror: continue @@ -389,10 +371,9 @@ def create_new_hec_key(hostname): if new_key: key = create_new_hec_key(formatted_hostname) - self.discovered_servers.append({"protocol": str(protocol), - "address": str(formatted_hostname), - "port": str(hec_port), - "key": str(key)}) + self.discovered_servers.append({ + "protocol": str(protocol), "address": str(formatted_hostname), "port": str(hec_port), "key": + str(key)}) counter += 1 except socket.gaierror: break @@ -477,9 +458,7 @@ def reset(self): self.log.exception(e) return '500', "Exception: {}".format(e.message) - ############################################## - ############ Event Handler Methods ########### - ############################################## + # Event Handler Methods @event_handler("eventgen_controller", "all_index", handler_type=BROADCAST, reliable_delivery=False) def event_handler_all_index(self, payload): @@ -602,9 +581,7 @@ def event_handler_set_volume(self, payload): def event_handler_reset(self, payload): return self.reset() - ############################################## - ################ HTTP Methods ################ - ############################################## + # HTTP Methods @http('GET', '/') def http_root(self, request): @@ -696,9 +673,7 @@ def http_set_volume(self, request): def http_reset(self, request): return json.dumps(self.reset()) - ############################################## - ################ Helper Methods ############## - ############################################## + # Helper Methods def parse_eventgen_conf(self, path): config = ConfigParser.ConfigParser() @@ -759,10 +734,7 @@ def get_data_volumes(self, config): def get_throughput(self): self.log.debug("Getting throughput ...") - empty_throughput = {'TOTAL_VOLUME_MB': 0, - 'TOTAL_COUNT': 0, - 'THROUGHPUT_VOLUME_KB': 0, - 'THROUGHPUT_COUNT': 0} + empty_throughput = {'TOTAL_VOLUME_MB': 0, 'TOTAL_COUNT': 0, 'THROUGHPUT_VOLUME_KB': 0, 'THROUGHPUT_COUNT': 0} if hasattr(self.eventgen_dependency.eventgen, 'output_counters'): total_volume = 0 total_count = 0 @@ -773,10 +745,9 @@ def get_throughput(self): total_count += output_counter.total_output_count throughput_volume += output_counter.throughput_volume throughput_count += output_counter.throughput_count - return {'TOTAL_VOLUME_MB': total_volume / (1024*1024), - 'TOTAL_COUNT': total_count, - 'THROUGHPUT_VOLUME_KB': throughput_volume / (1024), - 'THROUGHPUT_COUNT': throughput_count} + return { + 'TOTAL_VOLUME_MB': total_volume / (1024 * 1024), 'TOTAL_COUNT': total_count, 'THROUGHPUT_VOLUME_KB': + throughput_volume / (1024), 'THROUGHPUT_COUNT': throughput_count} else: self.log.debug("return empty throughput because of output_counters not found.") - return empty_throughput \ No newline at end of file + return empty_throughput diff --git a/splunk_eventgen/identitygen.py b/splunk_eventgen/identitygen.py index a0c29939..f95a1047 100644 --- a/splunk_eventgen/identitygen.py +++ b/splunk_eventgen/identitygen.py @@ -4,115 +4,135 @@ import time from string import ascii_uppercase -BASE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__),"..")) +BASE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) + class identityGenerator(object): - ''' - Generates csv file with the following values - ''' - CATEGORIES = ["cardholder","cardholder|pci","officer|pci","intern","default","default","default","default","sox","pci","officer","","","","","","","","","",""] - LOCATION = [["San Francisco","USA","americas","37.3382N","121.6663W"],["San Jose","USA","americas","37.78N","122.41W"]] - EMAIL_DOMAIN = "@splunk.com" - PRIORITIES = ["low","low","low","low","low","low","medium","medium","high","critical"] - def __init__(self): - try: - self.last = [i.split()[0] for i in open("%s/samples/dist.all.last"%BASE_PATH,"rb").readlines()] - except IOError as e: - self.last = [(''.join(random.choice(ascii_uppercase) for i in xrange(random.randint(4,12)))) for i in xrange(100)] - try: - self.female_first = [i.split()[0] for i in open("%s/samples/dist.female.first"%BASE_PATH,"rb").readlines()] - except IOError as e: - self.female_first = [(''.join(random.choice(ascii_uppercase) for i in xrange(random.randint(4,12)))) for i in xrange(100)] - try: - self.male_first = [i.split()[0] for i in open("%s/samples/dist.male.first"%BASE_PATH,"rb").readlines()] - except IOError as e: - self.male_first = [(''.join(random.choice(ascii_uppercase) for i in xrange(random.randint(4,12)))) for i in xrange(100)] + """ + Generates csv file with the following values + """ + CATEGORIES = [ + "cardholder", "cardholder|pci", "officer|pci", "intern", "default", "default", "default", "default", "sox", + "pci", "officer", "", "", "", "", "", "", "", "", "", ""] + LOCATION = [["San Francisco", "USA", "americas", "37.3382N", "121.6663W"], + ["San Jose", "USA", "americas", "37.78N", "122.41W"]] + EMAIL_DOMAIN = "@splunk.com" + PRIORITIES = ["low", "low", "low", "low", "low", "low", "medium", "medium", "high", "critical"] + + def __init__(self): + try: + self.last = [i.split()[0] for i in open("%s/samples/dist.all.last" % BASE_PATH, "rb").readlines()] + except IOError: + self.last = [ + (''.join(random.choice(ascii_uppercase) for i in xrange(random.randint(4, 12)))) for i in xrange(100)] + try: + self.female_first = [ + i.split()[0] for i in open("%s/samples/dist.female.first" % BASE_PATH, "rb").readlines()] + except IOError: + self.female_first = [ + (''.join(random.choice(ascii_uppercase) for i in xrange(random.randint(4, 12)))) for i in xrange(100)] + try: + self.male_first = [i.split()[0] for i in open("%s/samples/dist.male.first" % BASE_PATH, "rb").readlines()] + except IOError: + self.male_first = [ + (''.join(random.choice(ascii_uppercase) for i in xrange(random.randint(4, 12)))) for i in xrange(100)] + + def generate(self, count): + self.identities = [] + usernames = dict() + username = "" + len_last = len(self.last) + len_male_first = len(self.male_first) + len_female_first = len(self.female_first) + for i in xrange(count): + gender = random.choice(["m", "f"]) + last_name = self.last[int(random.triangular(0, len_last, 0))] + if gender == "m": + first_name = self.male_first[int(random.triangular(0, len_male_first, 0))] + else: + first_name = self.female_first[int(random.triangular(0, len_female_first, 0))] + category = random.choice(self.CATEGORIES) + priority = random.choice(self.PRIORITIES) + startDate = time.strftime("%m/%d/%Y", time.localtime(time.time() - random.randint(2592000, 77760000)) + ) # random start date between 30 days ago to 900 days ago + (work_city, work_country, bunit, work_lat, work_long) = random.choice(self.LOCATION) + identity = { + "first_name": first_name, "last_name": last_name, "work_city": work_city, "work_country": work_country, + "bunit": bunit, "work_lat": work_lat, "work_long": work_long, "priority": priority, "category": + category, "startDate": startDate} + base_username = identity["first_name"] + identity["last_name"] + if base_username in usernames: + tmp_val = 0 + while username + str(tmp_val) in usernames[base_username]: + tmp_val += 1 + username = base_username + str(tmp_val) + usernames[base_username].append(username) + else: + username = base_username + usernames[username] = list() + identity["username"] = username + identity["ip"] = self.int2InternalIP(i) + self.identities.append(identity) - def generate(self, count): - self.identities = [] - usernames = dict() - len_last = len(self.last) - len_male_first = len(self.male_first) - len_female_first = len(self.female_first) - prev_time = time.time() - for i in xrange(count): - gender = random.choice(["m","f"]) - last_name = self.last[int(random.triangular(0,len_last,0))] - if gender == "m": - first_name = self.male_first[int(random.triangular(0,len_male_first,0))] - else: - first_name = self.female_first[int(random.triangular(0,len_female_first,0))] - category = random.choice(self.CATEGORIES) - priority = random.choice(self.PRIORITIES) - startDate = time.strftime("%m/%d/%Y", time.localtime(time.time()-random.randint(2592000,77760000))) # random start date between 30 days ago to 900 days ago - (work_city, work_country, bunit, work_lat, work_long)= random.choice(self.LOCATION) - identity = {"first_name":first_name,"last_name":last_name,"work_city":work_city,"work_country":work_country,"bunit":bunit,"work_lat":work_lat,"work_long":work_long,"priority":priority,"category":category,"startDate":startDate} - base_username = identity["first_name"] + identity["last_name"] - t = time.time() - if base_username in usernames: - tmp_val = 0 - while username + str(tmp_val) in usernames[base_username]: - tmp_val += 1 - username = base_username + str(tmp_val) - usernames[base_username].append(username) - else: - username = base_username - usernames[username] = list() - identity["username"] = username - identity["ip"] = self.int2InternalIP(i) - self.identities.append(identity) - + def int2InternalIP(self, i): + return "10.%s.%s.%s" % (str(int(i / 65536)), str(int(i / 256) % 256), str(i % 256)) - def int2InternalIP(self,i): - return "10.%s.%s.%s" % (str(int(i/65536)), str(int(i/256)%256), str(i%256)) + def setLocations(self, new_locations): + for location in new_locations: + if len(location) != 5: + raise ValueError + self.CATEGORIES = new_locations - def setLocations(self,new_locations): - for location in new_locations: - if len(location)!=5: - raise ValueError - self.CATEGORIES = new_locations + def setCategories(self, new_categories): + self.CATEGORIES = new_categories - def setCategories(self,new_categories): - self.CATEGORIES = new_categories + def setEmail(self, new_email): + if "@" in new_email: + self.EMAIL_DOMAIN = new_email + else: + raise ValueError - def setEmail(self,new_email): - if "@" in new_email: - self.EMAIL_DOMAIN = new_email - else: - raise ValueError + def getFile(self, count=0, filename="../default", fields=["username", "first_name", "last_name"], fieldnames=[ + "username", "first_name", "last_name"]): + """ + Returns a rest endpoint to download a csv file + """ + if count == 0: + with open(filename, "wb") as lookupFile: + file = csv.writer(lookupFile) + file.writerow(fieldnames) + for identity in self.identities: + row = [] + for field in fields: + try: + row.append(identity[field]) + except KeyError: + row.append("") + file.writerow(row) + else: + with open(filename, "wb") as lookupFile: + file = csv.writer(lookupFile) + file.writerow(fieldnames) + for i in xrange(min(count + 1, len(self.identities))): # + 1 to account for the header + row = [] + identity = self.identities[i] + for field in fields: + try: + row.append(identity[field]) + except KeyError: + row.append("") + file.writerow(row) + return open(filename, "rb") - def getFile(self,count=0,filename="../default",fields=["username","first_name","last_name"],fieldnames=["username","first_name","last_name"]): - 'Returns a rest endpoint to download a csv file' - if count == 0: - with open(filename,"wb") as lookupFile: - file = csv.writer(lookupFile) - file.writerow(fieldnames) - for identity in self.identities: - row = [] - for field in fields: - try: - row.append(identity[field]) - except KeyError: - row.append("") - file.writerow(row) - else: - with open(filename,"wb") as lookupFile: - file = csv.writer(lookupFile) - file.writerow(fieldnames) - for i in xrange(min(count+1,len(identities))): # + 1 to account for the header - row = [] - identity = identities[i] - for field in fields: - try: - row.append(identity[field]) - except KeyError: - row.append("") - file.writerow(row) - return open(filename,"rb") if __name__ == "__main__": - identityGenerator = identityGenerator() - identityGenerator.generate(300000) - identityGenerator.getFile(filename="identities.csv", - fields=["username","prefix","username","first_name","last_name","suffix","email","phone","phone2","managedBy","priority","bunit","category","watchlist","startDate","endDate","work_city","work_country","work_lat","work_long"], - fieldnames = ["identity","prefix","nick","first","last","suffix","email","phone","phone2","managedBy","priority","bunit","category","watchlist","startDate","endDate","work_city","work_country","work_lat","work_long"]) \ No newline at end of file + identityGenerator = identityGenerator() + identityGenerator.generate(300000) + identityGenerator.getFile( + filename="identities.csv", fields=[ + "username", "prefix", "username", "first_name", "last_name", "suffix", "email", "phone", "phone2", + "managedBy", "priority", "bunit", "category", "watchlist", "startDate", "endDate", "work_city", + "work_country", "work_lat", "work_long"], fieldnames=[ + "identity", "prefix", "nick", "first", "last", "suffix", "email", "phone", "phone2", "managedBy", + "priority", "bunit", "category", "watchlist", "startDate", "endDate", "work_city", "work_country", + "work_lat", "work_long"]) diff --git a/splunk_eventgen/lib/eventgenconfig.py b/splunk_eventgen/lib/eventgenconfig.py index 161fca6b..d9382bfc 100644 --- a/splunk_eventgen/lib/eventgenconfig.py +++ b/splunk_eventgen/lib/eventgenconfig.py @@ -1,17 +1,20 @@ from __future__ import division -from ConfigParser import ConfigParser -import os + import datetime -import re -import logging, logging.handlers import json +import logging +import logging.handlers +import os import pprint +import random +import re +import types +import urllib +from ConfigParser import ConfigParser + +from eventgenexceptions import FailedLoadingPlugin, PluginNotLoaded from eventgensamples import Sample from eventgentoken import Token -from eventgenexceptions import PluginNotLoaded, FailedLoadingPlugin -import urllib -import types -import random # 4/21/14 CS Adding a defined constant whether we're running in standalone mode or not # Standalone mode is when we know we're Splunk embedded but we want to force @@ -50,11 +53,11 @@ class Config(object): sessionKey = None grandparentdir = None greatgrandparentdir = None - samples = [ ] + samples = [] sampleDir = None outputWorkers = None generatorWorkers = None - sampleTimers = [ ] + sampleTimers = [] # Config file options. We do not define defaults here, rather we pull them in # from eventgen.conf. @@ -65,10 +68,10 @@ class Config(object): disabled = None blacklist = ".*\.part" - __generatorworkers = [ ] - __outputworkers = [ ] - outputPlugins = { } - plugins = { } + __generatorworkers = [] + __outputworkers = [] + outputPlugins = {} + plugins = {} outputQueue = None generatorQueue = None args = None @@ -82,30 +85,32 @@ class Config(object): 'minuteOfHourRate', 'timezone', 'dayOfMonthRate', 'monthOfYearRate', 'perDayVolume', 'outputWorkers', 'generator', 'rater', 'generatorWorkers', 'timeField', 'sampleDir', 'threading', 'profiler', 'maxIntervalsBeforeFlush', 'maxQueueLength', 'splunkMethod', 'splunkPort', - 'verbosity', 'useOutputQueue', 'seed','end', 'autotimestamps', 'autotimestamp', 'httpeventWaitResponse', 'outputCounter', 'sequentialTimestamp'] + 'verbosity', 'useOutputQueue', 'seed','end', 'autotimestamps', 'autotimestamp', 'httpeventWaitResponse', + 'outputCounter', 'sequentialTimestamp', 'extendIndexes'] _validTokenTypes = {'token': 0, 'replacementType': 1, 'replacement': 2} _validHostTokens = {'token': 0, 'replacement': 1} - _validReplacementTypes = ['static', 'timestamp', 'replaytimestamp', 'random', 'rated', 'file', 'mvfile', 'seqfile', 'integerid'] - validOutputModes = [ ] + _validReplacementTypes = [ + 'static', 'timestamp', 'replaytimestamp', 'random', 'rated', 'file', 'mvfile', 'seqfile', 'integerid'] + validOutputModes = [] _intSettings = ['interval', 'outputWorkers', 'generatorWorkers', 'maxIntervalsBeforeFlush', 'maxQueueLength'] _floatSettings = ['randomizeCount', 'delay', 'timeMultiple'] - _boolSettings = ['disabled', 'randomizeEvents', 'bundlelines', 'profiler', 'useOutputQueue', 'autotimestamp', 'httpeventWaitResponse', 'outputCounter', 'sequentialTimestamp'] - _jsonSettings = ['hourOfDayRate', 'dayOfWeekRate', 'minuteOfHourRate', 'dayOfMonthRate', 'monthOfYearRate', 'autotimestamps'] - _defaultableSettings = ['disabled', 'spoolDir', 'spoolFile', 'breaker', 'sampletype', 'interval', 'delay', - 'count', 'bundlelines', 'earliest', 'latest', 'hourOfDayRate', 'dayOfWeekRate', - 'randomizeCount', 'randomizeEvents', 'outputMode', 'fileMaxBytes', 'fileBackupFiles', - 'splunkHost', 'splunkPort', 'splunkMethod', 'index', 'source', 'sourcetype', 'host', 'hostRegex', - 'projectID', 'accessToken', 'mode', 'minuteOfHourRate', 'timeMultiple', 'dayOfMonthRate', - 'monthOfYearRate', 'perDayVolume', 'sessionKey', 'generator', 'rater', 'timeField', 'maxQueueLength', - 'maxIntervalsBeforeFlush', 'autotimestamp'] - _complexSettings = { 'sampletype': ['raw', 'csv'], - 'mode': ['sample', 'replay'], - 'threading': ['thread', 'process']} + _boolSettings = [ + 'disabled', 'randomizeEvents', 'bundlelines', 'profiler', 'useOutputQueue', 'autotimestamp', + 'httpeventWaitResponse', 'outputCounter', 'sequentialTimestamp'] + _jsonSettings = [ + 'hourOfDayRate', 'dayOfWeekRate', 'minuteOfHourRate', 'dayOfMonthRate', 'monthOfYearRate', 'autotimestamps'] + _defaultableSettings = [ + 'disabled', 'spoolDir', 'spoolFile', 'breaker', 'sampletype', 'interval', 'delay', 'count', 'bundlelines', + 'earliest', 'latest', 'hourOfDayRate', 'dayOfWeekRate', 'randomizeCount', 'randomizeEvents', 'outputMode', + 'fileMaxBytes', 'fileBackupFiles', 'splunkHost', 'splunkPort', 'splunkMethod', 'index', 'source', 'sourcetype', + 'host', 'hostRegex', 'projectID', 'accessToken', 'mode', 'minuteOfHourRate', 'timeMultiple', 'dayOfMonthRate', + 'monthOfYearRate', 'perDayVolume', 'sessionKey', 'generator', 'rater', 'timeField', 'maxQueueLength', + 'maxIntervalsBeforeFlush', 'autotimestamp'] + _complexSettings = {'sampletype': ['raw', 'csv'], 'mode': ['sample', 'replay'], 'threading': ['thread', 'process']} def __init__(self, configfile=None, sample=None, override_outputter=False, override_count=False, - override_interval=False, override_backfill=False, override_end=False, - threading="thread", override_generators=None, override_outputqueue=False, - profiler=False, verbosity=40): + override_interval=False, override_backfill=False, override_end=False, threading="thread", + override_generators=None, override_outputqueue=False, profiler=False, verbosity=40): """Setup Config object. Sets up Logging and path related variables.""" # Rebind the internal datastore of the class to an Instance variable self.__dict__ = self.__sharedState @@ -144,18 +149,18 @@ def __init__(self, configfile=None, sample=None, override_outputter=False, overr self.stopping = False - #self.copyLock = threading.Lock() if self.threading == 'thread' else multiprocessing.Lock() + # self.copyLock = threading.Lock() if self.threading == 'thread' else multiprocessing.Lock() self._firsttime = False def __str__(self): """Only used for debugging, outputs a pretty printed representation of our Config""" # Filter items from config we don't want to pretty print - filter_list = [ 'samples', 'sampleTimers', '__generatorworkers', '__outputworkers' ] + filter_list = ['samples', 'sampleTimers', '__generatorworkers', '__outputworkers'] # Eliminate recursive going back to parent - temp = dict([ (key, value) for (key, value) in self.__dict__.items() if key not in filter_list ]) + temp = dict([(key, value) for (key, value) in self.__dict__.items() if key not in filter_list]) - return 'Config:'+pprint.pformat(temp)+'\nSamples:\n'+pprint.pformat(self.samples) + return 'Config:' + pprint.pformat(temp) + '\nSamples:\n' + pprint.pformat(self.samples) # loggers can't be pickled due to the lock object, remove them before we try to pickle anything. def __getstate__(self): @@ -173,14 +178,13 @@ def _setup_logging(self): def getPlugin(self, name, s=None): """Return a reference to a Python object (not an instance) referenced by passed name""" - ''' APPPERF-263: make sure we look in __outputPlugins as well. For some reason we keep 2 separate dicts of plugins. ''' - plugintype=name.split(".")[0] - if not name in self.plugins and not name in self.outputPlugins: + plugintype = name.split(".")[0] + if name not in self.plugins and name not in self.outputPlugins: # 2/1/15 CS If we haven't already seen the plugin, try to load it # Note, this will only work for plugins which do not specify config validation # parameters. If they do, configs may not validate for user provided plugins. @@ -189,14 +193,14 @@ def getPlugin(self, name, s=None): plugin = getattr(s, plugintype) else: plugin = getattr(s, 'outputMode') - if plugin != None: - self.logger.debug("Attempting to dynamically load plugintype '%s' named '%s' for sample '%s'" - % (plugintype, plugin, s.name)) + if plugin is not None: + self.logger.debug("Attempting to dynamically load plugintype '%s' named '%s' for sample '%s'" % + (plugintype, plugin, s.name)) bindir = os.path.join(s.sampleDir, os.pardir, 'bin') libdir = os.path.join(s.sampleDir, os.pardir, 'lib') plugindir = os.path.join(libdir, 'plugins', plugintype) - targetplugin = PluginNotLoaded(bindir=bindir, libdir=libdir, - plugindir=plugindir, name=plugin, type=plugintype) + targetplugin = PluginNotLoaded(bindir=bindir, libdir=libdir, plugindir=plugindir, name=plugin, + type=plugintype) if targetplugin.name not in self.extraplugins: self.extraplugins.append(targetplugin.name) raise targetplugin @@ -204,7 +208,7 @@ def getPlugin(self, name, s=None): raise FailedLoadingPlugin(name=plugin) # APPPERF-263: consult both __outputPlugins and __plugins - if not name in self.plugins and not name in self.outputPlugins: + if name not in self.plugins and name not in self.outputPlugins: raise KeyError('Plugin ' + name + ' not found') # return in order of precedence: __plugins, __outputPlugins, None @@ -218,7 +222,7 @@ def makeSplunkEmbedded(self, sessionKey): def getSplunkUrl(self, s): """ - Get Splunk URL. If we're embedded in Splunk, get it from Splunk's Python libraries, otherwise get it from config. + If we're embedded in Splunk, get it from Splunk's Python libraries, otherwise get it from config. Returns a tuple of ( splunkUrl, splunkMethod, splunkHost, splunkPort ) """ @@ -233,11 +237,14 @@ def getSplunkUrl(self, s): except: import traceback trace = traceback.format_exc() - self.logger.error('Error parsing host from splunk.auth.splunk.getLocalServerInfo() for sample %s. Stacktrace: %s' % (s.name, trace)) - raise ValueError('Error parsing host from splunk.auth.splunk.getLocalServerInfo() for sample %s' % s.name) + self.logger.error( + 'Error parsing host from splunk.auth.splunk.getLocalServerInfo() for sample %s. Stacktrace: %s' % + (s.name, trace)) + raise ValueError( + 'Error parsing host from splunk.auth.splunk.getLocalServerInfo() for sample %s' % s.name) else: # splunkMethod and splunkPort are defaulted so only check for splunkHost - if s.splunkHost == None: + if s.splunkHost is None: self.logger.error("Splunk URL Requested but splunkHost not set for sample '%s'" % s.name) raise ValueError("Splunk URL Requested but splunkHost not set for sample '%s'" % s.name) @@ -246,7 +253,8 @@ def getSplunkUrl(self, s): splunkHost = s.splunkHost splunkPort = s.splunkPort - self.logger.debug("Getting Splunk URL: %s Method: %s Host: %s Port: %s" % (splunkUrl, splunkMethod, splunkHost, splunkPort)) + self.logger.debug( + "Getting Splunk URL: %s Method: %s Host: %s Port: %s" % (splunkUrl, splunkMethod, splunkHost, splunkPort)) return (splunkUrl, splunkMethod, splunkHost, splunkPort) def parse(self): @@ -267,8 +275,8 @@ def parse(self): if 'default' in self._confDict: del self._confDict['default'] - tempsamples = [ ] - tempsamples2 = [ ] + tempsamples = [] + tempsamples2 = [] stanza_map = {} stanza_list = [] @@ -322,7 +330,8 @@ def parse(self): if 'token.{}.token'.format(i) in self._confDict[global_stanza]: token = self._confDict[global_stanza].get('token.{}.token'.format(i)) replacement = self._confDict[global_stanza].get('token.{}.replacement'.format(i)) - replacementType = self._confDict[global_stanza].get('token.{}.replacementType'.format(i)) + replacementType = self._confDict[global_stanza].get( + 'token.{}.replacementType'.format(i)) last_token_number += 1 if token: @@ -343,9 +352,9 @@ def parse(self): break keys = settings.keys() - for k,v in self._confDict[global_stanza].items(): + for k, v in self._confDict[global_stanza].items(): if 'token' not in k and k not in keys: - kv_pair_items.append((k,v)) + kv_pair_items.append((k, v)) for key, value in kv_pair_items: oldvalue = value @@ -359,7 +368,7 @@ def parse(self): # Token indices could be out of order, so we must check to # see whether we have enough items in the list to update the token # In general this will keep growing the list by whatever length we need - if(key.find("host.") > -1): + if (key.find("host.") > -1): # self.logger.info("hostToken.{} = {}".format(value[1],oldvalue)) if not isinstance(s.hostToken, Token): s.hostToken = Token(s) @@ -368,8 +377,8 @@ def parse(self): setattr(s.hostToken, value[0], oldvalue) else: if len(s.tokens) <= value[0]: - x = (value[0]+1) - len(s.tokens) - s.tokens.extend([None for i in xrange(0, x)]) + x = (value[0] + 1) - len(s.tokens) + s.tokens.extend([None for num in xrange(0, x)]) if not isinstance(s.tokens[value[0]], Token): s.tokens[value[0]] = Token(s) # logger.info("token[{}].{} = {}".format(value[0],value[1],oldvalue)) @@ -383,42 +392,39 @@ def parse(self): s._lockedSettings.append(key) # self.logger.debug("Appending '%s' to locked settings for sample '%s'" % (key, s.name)) - - # Validate all the tokens are fully setup, can't do this in _validateSettings # because they come over multiple lines # Don't error out at this point, just log it and remove the token and move on - deleteidx = [ ] + deleteidx = [] for i in xrange(0, len(s.tokens)): t = s.tokens[i] # If the index doesn't exist at all - if t == None: + if t is None: self.logger.error("Token at index %s invalid" % i) # Can't modify list in place while we're looping through it # so create a list to remove later deleteidx.append(i) - elif t.token == None or t.replacementType == None or t.replacement == None: + elif t.token is None or t.replacementType is None or t.replacement is None: self.logger.error("Token at index %s invalid" % i) deleteidx.append(i) - newtokens = [ ] + newtokens = [] for i in xrange(0, len(s.tokens)): if i not in deleteidx: newtokens.append(s.tokens[i]) s.tokens = newtokens - # Must have eai:acl key to determine app name which determines where actual files are - if s.app == None: + if s.app is None: self.logger.error("App not set for sample '%s' in stanza '%s'" % (s.name, stanza)) raise ValueError("App not set for sample '%s' in stanza '%s'" % (s.name, stanza)) # Set defaults for items not included in the config file for setting in self._defaultableSettings: - if not hasattr(s, setting) or getattr(s, setting) == None: + if not hasattr(s, setting) or getattr(s, setting) is None: setattr(s, setting, getattr(self, setting, None)) # Append to temporary holding list if not s.disabled: - s._priority = len(tempsamples)+1 + s._priority = len(tempsamples) + 1 tempsamples.append(s) # 6/22/12 CS Rewriting the config matching code yet again to handling flattening better. @@ -427,14 +433,15 @@ def parse(self): # every other match to that one. for s in tempsamples: # Now we need to match this up to real files. May generate multiple copies of the sample. - foundFiles = [ ] + foundFiles = [] # 1/5/14 Adding a config setting to override sample directory, primarily so I can put tests in their own # directories - if s.sampleDir == None: + if s.sampleDir is None: self.logger.debug("Sample directory not specified in config, setting based on standard") if self.splunkEmbedded and not STANDALONE: - s.sampleDir = os.path.normpath(os.path.join(self.grandparentdir, '..', '..', '..', s.app, 'samples')) + s.sampleDir = os.path.normpath( + os.path.join(self.grandparentdir, '..', '..', '..', s.app, 'samples')) else: # 2/1/15 CS Adding support for looking for samples based on the config file specified on # the command line. @@ -452,7 +459,8 @@ def parse(self): if not os.path.exists(s.sampleDir): newSampleDir = os.path.join(self.grandparentdir, 'samples') - self.logger.error("Path not found for samples '%s', trying '%s'" % (s.sampleDir, newSampleDir)) + self.logger.error( + "Path not found for samples '%s', trying '%s'" % (s.sampleDir, newSampleDir)) s.sampleDir = newSampleDir else: self.logger.debug("Sample directory specified in config, checking for relative") @@ -485,10 +493,12 @@ def parse(self): self.maxIntervalsBeforeFlush = 1 s.maxIntervalsBeforeFlush = 1 s.maxQueueLength = s.maxQueueLength or 1 - self.logger.debug("Sample '%s' setting maxQueueLength to '%s' from command line" % (s.name, s.maxQueueLength)) + self.logger.debug( + "Sample '%s' setting maxQueueLength to '%s' from command line" % (s.name, s.maxQueueLength)) if self.override_outputter: - self.logger.debug("Sample '%s' setting output to '%s' from command line" % (s.name, self.override_outputter)) + self.logger.debug( + "Sample '%s' setting output to '%s' from command line" % (s.name, self.override_outputter)) s.outputMode = self.override_outputter if self.override_count: @@ -498,11 +508,13 @@ def parse(self): s.backfill = None if self.override_interval: - self.logger.debug("Overriding interval to '%d' for sample '%s'" % (self.override_interval, s.name)) + self.logger.debug( + "Overriding interval to '%d' for sample '%s'" % (self.override_interval, s.name)) s.interval = self.override_interval if self.override_backfill: - self.logger.debug("Overriding backfill to '%s' for sample '%s'" % (self.override_backfill, s.name)) + self.logger.debug( + "Overriding backfill to '%s' for sample '%s'" % (self.override_backfill, s.name)) s.backfill = self.override_backfill.lstrip() if self.override_end: @@ -517,7 +529,7 @@ def parse(self): for token in s.tokens: if token.replacementType == 'integerid': try: - stateFile = open(os.path.join(s.sampleDir, 'state.'+urllib.pathname2url(token.token)), 'rU') + stateFile = open(os.path.join(s.sampleDir, 'state.' + urllib.pathname2url(token.token)), 'rU') token.replacement = stateFile.read() stateFile.close() # The file doesn't exist, use the default value in the config @@ -532,8 +544,9 @@ def parse(self): self.logger.debug("Matched file {0} with sample name {1}".format(results.group(0), s.name)) samplePath = os.path.join(s.sampleDir, sample) if os.path.isfile(samplePath): - self.logger.debug("Found sample file '%s' for app '%s' using config '%s' with priority '%s'; adding to list" \ - % (sample, s.app, s.name, s._priority) ) + self.logger.debug( + "Found sample file '%s' for app '%s' using config '%s' with priority '%s'" % + (sample, s.app, s.name, s._priority) + "; adding to list") foundFiles.append(samplePath) # If we didn't find any files, log about it @@ -554,9 +567,9 @@ def parse(self): # Override with real name if s.outputMode == 'spool' and s.spoolFile == self.spoolFile: news.spoolFile = f.split(os.sep)[-1] - if s.outputMode == 'file' and s.fileName == None and s.spoolFile == self.spoolFile: + if s.outputMode == 'file' and s.fileName is None and s.spoolFile == self.spoolFile: news.fileName = os.path.join(s.spoolDir, f.split(os.sep)[-1]) - elif s.outputMode == 'file' and s.fileName == None and s.spoolFile != None: + elif s.outputMode == 'file' and s.fileName is None and s.spoolFile is not None: news.fileName = os.path.join(s.spoolDir, s.spoolFile) # Override s.name with file name. Usually they'll match unless we've been a regex # 6/22/12 CS Save original name for later matching @@ -568,7 +581,7 @@ def parse(self): self.logger.info("Sample '%s' for app '%s' is marked disabled." % (news.name, news.app)) # Clear tempsamples, we're going to reuse it - tempsamples = [ ] + tempsamples = [] # We're now going go through the samples and attempt to apply any matches from other stanzas # This allows us to specify a wildcard at the beginning of the file and get more specific as we go on @@ -576,25 +589,26 @@ def parse(self): # Loop through all samples, create a list of the master samples for s in tempsamples2: foundHigherPriority = False - othermatches = [ ] + othermatches = [] # If we're an exact match, don't go looking for higher priorities if not s.name == s._origName: for matchs in tempsamples2: if matchs.filePath == s.filePath and s._origName != matchs._origName: # We have a match, now determine if we're higher priority or not - # If this is a longer pattern or our match is an exact match - # then we're a higher priority match + # If this is a longer pattern or our match is an exact match + # then we're a higher priority match if len(matchs._origName) > len(s._origName) or matchs.name == matchs._origName: # if s._priority < matchs._priority: - self.logger.debug("Found higher priority for sample '%s' with priority '%s' from sample '%s' with priority '%s'" \ - % (s._origName, s._priority, matchs._origName, matchs._priority)) + self.logger.debug("Found higher priority for sample '%s' with priority '%s' from sample " % + (s._origName, s._priority) + + "'%s' with priority '%s'" % (matchs._origName, matchs._priority)) foundHigherPriority = True break else: othermatches.append(matchs._origName) if not foundHigherPriority: - self.logger.debug("Chose sample '%s' from samples '%s' for file '%s'" \ - % (s._origName, othermatches, s.name)) + self.logger.debug( + "Chose sample '%s' from samples '%s' for file '%s'" % (s._origName, othermatches, s.name)) tempsamples.append(s) # Now we have two lists, tempsamples which contains only the highest priority matches, and @@ -625,13 +639,14 @@ def parse(self): # 6/22/12 CS Added support for non-overrideable (locked) settings # logger.debug("Locked settings: %s" % pprint.pformat(matchs._lockedSettings)) # if settingname in matchs._lockedSettings: - # logger.debug("Matched setting '%s' in sample '%s' lockedSettings" \ + # logger.debug("Matched setting '%s' in sample '%s' lockedSettings" # % (settingname, matchs.name)) - if (destsetting == None or destsetting == getattr(self, settingname)) \ - and sourcesetting != None and sourcesetting != getattr(self, settingname) \ - and not settingname in s._lockedSettings: - self.logger.debug("Overriding setting '%s' with value '%s' from sample '%s' to sample '%s' in app '%s'" \ - % (settingname, sourcesetting, overridesample._origName, s.name, s.app)) + if (destsetting is None or destsetting == getattr(self, settingname)) \ + and sourcesetting is not None and sourcesetting != getattr(self, settingname) \ + and settingname not in s._lockedSettings: + self.logger.debug("Overriding setting '%s' with value '%s' from sample '%s' to " % + (settingname, sourcesetting, overridesample._origName) + + "sample '%s' in app '%s'" % (s.name, s.app)) setattr(s, settingname, sourcesetting) except AttributeError: pass @@ -649,7 +664,8 @@ def parse(self): # We've added replay mode, so lets loop through the samples again and set the earliest and latest # settings for any samples that were set to replay mode if s.perDayVolume: - self.logger.info("Stanza contains per day volume, changing rater and generator to perdayvolume instead of count") + self.logger.info( + "Stanza contains per day volume, changing rater and generator to perdayvolume instead of count") s.rater = 'perdayvolume' s.count = 1 s.generator = 'perdayvolumegenerator' @@ -676,7 +692,7 @@ def parse(self): if s.autotimestamp: at = self.autotimestamps - line_puncts = [ ] + line_puncts = [] # Check for _time field, if it exists, add a timestamp to support it if len(s.sampleDict) > 0: @@ -712,7 +728,8 @@ def parse(self): t.replacement = x[1] try: - self.logger.debug("Trying regex '%s' for format '%s' on '%s'" % (x[0], x[1], e[s.timeField])) + self.logger.debug( + "Trying regex '%s' for format '%s' on '%s'" % (x[0], x[1], e[s.timeField])) ts = s.getTSFromEvent(e['_raw'], t) if type(ts) == datetime.datetime: found_token = False @@ -722,10 +739,11 @@ def parse(self): found_token = True break if not found_token: - self.logger.debug("Found timestamp '%s', extending token with format '%s'" % (x[0], x[1])) + self.logger.debug( + "Found timestamp '%s', extending token with format '%s'" % (x[0], x[1])) s.tokens.append(t) # Drop this pattern from ones we try in the future - at = [ z for z in at if z[0] != x[0] ] + at = [z for z in at if z[0] != x[0]] break except ValueError: pass @@ -749,23 +767,23 @@ def _validateSetting(self, stanza, key, value): self.logger.debug("Validating setting for '%s' with value '%s' in stanza '%s'" % (key, value, stanza)) if key.find('token.') > -1: results = re.match('token\.(\d+)\.(\w+)', key) - if results != None: + if results is not None: groups = results.groups() if groups[1] not in self._validTokenTypes: - self.logger.error("Could not parse token index '%s' token type '%s' in stanza '%s'" % \ - (groups[0], groups[1], stanza)) - raise ValueError("Could not parse token index '%s' token type '%s' in stanza '%s'" % \ - (groups[0], groups[1], stanza)) + self.logger.error("Could not parse token index '%s' token type '%s' in stanza '%s'" % + (groups[0], groups[1], stanza)) + raise ValueError("Could not parse token index '%s' token type '%s' in stanza '%s'" % + (groups[0], groups[1], stanza)) if groups[1] == 'replacementType': if value not in self._validReplacementTypes: - self.logger.error("Invalid replacementType '%s' for token index '%s' in stanza '%s'" % \ - (value, groups[0], stanza)) - raise ValueError("Could not parse token index '%s' token type '%s' in stanza '%s'" % \ - (groups[0], groups[1], stanza)) + self.logger.error("Invalid replacementType '%s' for token index '%s' in stanza '%s'" % + (value, groups[0], stanza)) + raise ValueError("Could not parse token index '%s' token type '%s' in stanza '%s'" % + (groups[0], groups[1], stanza)) return (int(groups[0]), groups[1]) elif key.find('host.') > -1: results = re.match('host\.(\w+)', key) - if results != None: + if results is not None: groups = results.groups() if groups[0] not in self._validHostTokens: self.logger.error("Could not parse host token type '%s' in stanza '%s'" % (groups[0], stanza)) @@ -811,8 +829,9 @@ def _validateSetting(self, stanza, key, value): self.logger.debug("Calling function for setting '%s' with value '%s'" % (key, value)) value = complexSetting(value) elif isinstance(complexSetting, list): - if not value in complexSetting: - self.logger.error("Setting '%s' is invalid for value '%s' in stanza '%s'" % (key, value, stanza)) + if value not in complexSetting: + self.logger.error( + "Setting '%s' is invalid for value '%s' in stanza '%s'" % (key, value, stanza)) raise ValueError("Setting '%s' is invalid for value '%s' in stanza '%s'" % (key, value, stanza)) else: # Notifying only if the setting isn't valid and continuing on @@ -832,7 +851,7 @@ def _validateTimezone(self, value): mod = 100 else: mod = -100 - value = datetime.timedelta(hours=int(int(value) / 100.0), minutes=int(value) % mod ) + value = datetime.timedelta(hours=int(int(value) / 100.0), minutes=int(value) % mod) except: self.logger.error("Could not parse timezone {}".format(value)) raise ValueError("Could not parse timezone {}".format(value)) @@ -855,7 +874,6 @@ def _buildConfDict(self): """Build configuration dictionary that we will use """ # Abstracts grabbing configuration from Splunk or directly from Configuration Files - if self.splunkEmbedded and not STANDALONE: self.logger.info('Retrieving eventgen configurations from /configs/eventgen') import splunk.entity as entity @@ -866,9 +884,7 @@ def _buildConfDict(self): conf = ConfigParser() # Make case sensitive conf.optionxform = str - currentdir = os.getcwd() - - conffiles = [ ] + conffiles = [] # 2/1/15 CS Moving to argparse way of grabbing command line parameters if self.configfile: if os.path.exists(self.configfile): @@ -876,26 +892,26 @@ def _buildConfDict(self): # In which case we'll assume it's a splunk app and look for config files in # default and local if os.path.isdir(self.configfile): - conffiles = [os.path.join(self.grandparentdir, 'default', 'eventgen.conf'), - os.path.join(self.configfile, 'default', 'eventgen.conf'), - os.path.join(self.configfile, 'local', 'eventgen.conf')] + conffiles = [ + os.path.join(self.grandparentdir, 'default', 'eventgen.conf'), + os.path.join(self.configfile, 'default', 'eventgen.conf'), + os.path.join(self.configfile, 'local', 'eventgen.conf')] else: - conffiles = [os.path.join(self.grandparentdir, 'default', 'eventgen.conf'), - self.configfile] + conffiles = [os.path.join(self.grandparentdir, 'default', 'eventgen.conf'), self.configfile] if len(conffiles) == 0: - conffiles = [os.path.join(self.grandparentdir, 'default', 'eventgen.conf'), - os.path.join(self.grandparentdir, 'local', 'eventgen.conf')] + conffiles = [ + os.path.join(self.grandparentdir, 'default', 'eventgen.conf'), + os.path.join(self.grandparentdir, 'local', 'eventgen.conf')] self.logger.debug('Reading configuration files for non-splunkembedded: %s' % conffiles) conf.read(conffiles) sections = conf.sections() - ret = { } - orig = { } + ret = {} for section in sections: ret[section] = dict(conf.items(section)) # For compatibility with Splunk's configs, need to add the app name to an eai:acl key - ret[section]['eai:acl'] = { 'app': self.grandparentdir.split(os.sep)[-1] } + ret[section]['eai:acl'] = {'app': self.grandparentdir.split(os.sep)[-1]} self._confDict = ret self.logger.debug("ConfDict returned %s" % pprint.pformat(dict(self._confDict))) diff --git a/splunk_eventgen/lib/eventgenexceptions.py b/splunk_eventgen/lib/eventgenexceptions.py index f954192c..3d0d0d91 100644 --- a/splunk_eventgen/lib/eventgenexceptions.py +++ b/splunk_eventgen/lib/eventgenexceptions.py @@ -3,9 +3,7 @@ """ - class PluginNotLoaded(Exception): - def __init__(self, bindir, libdir, plugindir, name, type, msg="Plugin {} Not Loaded, attempting to load."): """Exception raised when a sample asks for a plugin that is not in the plugin list. This exception triggers an upload reload of plugins that expands the search path of plugins to add. @@ -26,8 +24,8 @@ def __init__(self, bindir, libdir, plugindir, name, type, msg="Plugin {} Not Loa self.type = type super(PluginNotLoaded, self).__init__(msg) -class FailedLoadingPlugin(Exception): +class FailedLoadingPlugin(Exception): def __init__(self, name, msg="Plugin {} Not Found or Failed to load."): """Exception raised when a sample asks for a plugin that can't be found diff --git a/splunk_eventgen/lib/eventgenoutput.py b/splunk_eventgen/lib/eventgenoutput.py index b8454dc6..c2b8c1c1 100644 --- a/splunk_eventgen/lib/eventgenoutput.py +++ b/splunk_eventgen/lib/eventgenoutput.py @@ -1,12 +1,13 @@ from __future__ import division + +import datetime import logging import logging.handlers -from Queue import Full -import json import time -import datetime +from Queue import Full + -#TODO: Figure out why we load plugins from here instead of the base plugin class. +# TODO: Figure out why we load plugins from here instead of the base plugin class. class Output(object): """ Base class which loads output plugins in BASE_DIR/lib/plugins/output and handles queueing @@ -22,11 +23,10 @@ def __init__(self, sample): self._setup_logging() self.output_counter = None - def __str__(self): """Only used for debugging, outputs a pretty printed representation of this output""" # Eliminate recursive going back to parent - temp = dict([ (key, value) for (key, value) in self.__dict__.items() if key != '_c']) + # temp = dict([(key, value) for (key, value) in self.__dict__.items() if key != '_c']) # return pprint.pformat(temp) return "" @@ -55,18 +55,18 @@ def setOutputCounter(self, output_counter): def updateConfig(self, config): self.config = config - #TODO: This is where the actual output plugin is loaded, and pushed out. This should be handled way better... + # TODO: This is where the actual output plugin is loaded, and pushed out. This should be handled way better... self.outputPlugin = self.config.getPlugin('output.' + self._sample.outputMode, self._sample) def send(self, msg): """ Adds msg to the output buffer, flushes if buffer is more than MAXQUEUELENGTH """ - ts = self._sample.timestamp if self._sample.timestamp != None else self._sample.now() - self._queue.append({'_raw': msg, 'index': self._sample.index, - 'source': self._sample.source, 'sourcetype': self._sample.sourcetype, - 'host': self._sample.host, 'hostRegex': self._sample.hostRegex, - '_time': int(time.mktime(ts.timetuple()))}) + ts = self._sample.timestamp if self._sample.timestamp is not None else self._sample.now() + self._queue.append({ + '_raw': msg, 'index': self._sample.index, 'source': self._sample.source, 'sourcetype': + self._sample.sourcetype, 'host': self._sample.host, 'hostRegex': self._sample.hostRegex, '_time': int( + time.mktime(ts.timetuple()))}) if len(self._queue) >= self.MAXQUEUELENGTH: self.flush() @@ -90,7 +90,7 @@ def flush(self, endOfInterval=False): more than maxIntervalsBeforeFlush tunable. """ flushing = False - #TODO: Fix interval flushing somehow with a queue, not sure I even want to support this feature anymore. + # TODO: Fix interval flushing somehow with a queue, not sure I even want to support this feature anymore. '''if endOfInterval: logger.debugv("Sample calling flush, checking increment against maxIntervalsBeforeFlush") c.intervalsSinceFlush[self._sample.name].increment() @@ -104,7 +104,7 @@ def flush(self, endOfInterval=False): logger.debugv("maxQueueLength exceeded, flushing") flushing = True''' - #TODO: This is set this way just for the time being while I decide if we want this feature. + # TODO: This is set this way just for the time being while I decide if we want this feature. flushing = True if flushing: q = self._queue @@ -113,8 +113,10 @@ def flush(self, endOfInterval=False): outputer = self.outputPlugin(self._sample, self.output_counter) outputer.updateConfig(self.config) outputer.set_events(q) - # When an outputQueue is used, it needs to run in a single threaded nature which requires to be put back into the outputqueue so a single thread worker can execute it. - # When an outputQueue is not used, it can be ran by multiple processes or threads. Therefore, no need to put the outputer back into the Queue. Just execute it. + # When an outputQueue is used, it needs to run in a single threaded nature which requires to be put back + # into the outputqueue so a single thread worker can execute it. When an outputQueue is not used, it can be + # ran by multiple processes or threads. Therefore, no need to put the outputer back into the Queue. Just + # execute it. # if outputPlugin must be used for useOutputQueue, use outputQueue regardless of user config useOutputQueue: if self.outputPlugin.useOutputQueue or self.config.useOutputQueue: try: @@ -126,9 +128,10 @@ def flush(self, endOfInterval=False): # TODO: clean out eventsSend and bytesSent if they are not being used in config # self.config.eventsSent.add(len(tmp)) # self.config.bytesSent.add(sum(tmp)) - if self.config.splunkEmbedded and len(tmp)>0: + if self.config.splunkEmbedded and len(tmp) > 0: metrics = logging.getLogger('eventgen_metrics') - metrics.info({'timestamp': datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S'), - 'sample': self._sample.name, 'events': len(tmp), 'bytes': sum(tmp)}) + metrics.info({ + 'timestamp': datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S'), 'sample': + self._sample.name, 'events': len(tmp), 'bytes': sum(tmp)}) tmp = None outputer.run() diff --git a/splunk_eventgen/lib/eventgensamples.py b/splunk_eventgen/lib/eventgensamples.py index 7e14fb3f..8a0c21b3 100644 --- a/splunk_eventgen/lib/eventgensamples.py +++ b/splunk_eventgen/lib/eventgensamples.py @@ -1,14 +1,17 @@ # TODO Move config settings to plugins from __future__ import division, with_statement -import os, sys + +import copy +import csv +import datetime import logging +import os import pprint -import datetime import re -import csv -import copy +import sys import urllib + from timeparser import timeParser @@ -23,7 +26,7 @@ class Sample(object): name = None app = None filePath = None - + # Options which are all valid for a sample disabled = None spoolDir = None @@ -83,6 +86,8 @@ class Sample(object): end = None queueable = None autotimestamp = None + extendIndexes = None + index_list = [] # Internal fields sampleLines = None @@ -93,11 +98,11 @@ class Sample(object): _lastts = None _earliestParsed = None _latestParsed = None - + def __init__(self, name): self.name = name - self.tokens = [ ] - self._lockedSettings = [ ] + self.tokens = [] + self._lockedSettings = [] self.backfilldone = False self._setup_logging() @@ -106,10 +111,10 @@ def updateConfig(self, config): def __str__(self): """Only used for debugging, outputs a pretty printed representation of this sample""" - filter_list = [ 'sampleLines', 'sampleDict' ] - temp = dict([ (key, value) for (key, value) in self.__dict__.items() if key not in filter_list ]) + filter_list = ['sampleLines', 'sampleDict'] + temp = dict([(key, value) for (key, value) in self.__dict__.items() if key not in filter_list]) return pprint.pformat(temp) - + def __repr__(self): return self.__str__() @@ -128,17 +133,17 @@ def _setup_logging(self): logger = logging.getLogger('eventgen') self.logger = logger - ## Replaces $SPLUNK_HOME w/ correct pathing + # Replaces $SPLUNK_HOME w/ correct pathing def pathParser(self, path): greatgreatgrandparentdir = os.path.dirname(os.path.dirname(self.config.grandparentdir)) sharedStorage = ['$SPLUNK_HOME/etc/apps', '$SPLUNK_HOME/etc/users/', '$SPLUNK_HOME/var/run/splunk'] - ## Replace windows os.sep w/ nix os.sep + # Replace windows os.sep w/ nix os.sep path = path.replace('\\', '/') - ## Normalize path to os.sep + # Normalize path to os.sep path = os.path.normpath(path) - ## Iterate special paths + # Iterate special paths for x in range(0, len(sharedStorage)): sharedPath = os.path.normpath(sharedStorage[x]) @@ -146,17 +151,17 @@ def pathParser(self, path): path.replace('$SPLUNK_HOME', greatgreatgrandparentdir) break - ## Split path + # Split path path = path.split(os.sep) - ## Iterate path segments + # Iterate path segments for x in range(0, len(path)): segment = path[x].lstrip('$') - ## If segement is an environment variable then replace - if os.environ.has_key(segment): + # If segement is an environment variable then replace + if segment in os.environ: path[x] = os.environ[segment] - ## Join path + # Join path path = os.sep.join(path) return path @@ -164,11 +169,11 @@ def pathParser(self, path): # 9/2/15 Adding ability to pass in a token rather than using the tokens from the sample def getTSFromEvent(self, event, passed_token=None): currentTime = None - formats = [ ] + formats = [] # JB: 2012/11/20 - Can we optimize this by only testing tokens of type = *timestamp? # JB: 2012/11/20 - Alternatively, documentation should suggest putting timestamp as token.0. - if passed_token != None: - tokens = [ passed_token ] + if passed_token is not None: + tokens = [passed_token] else: tokens = self.tokens for token in tokens: @@ -182,14 +187,16 @@ def getTSFromEvent(self, event, passed_token=None): timeString = results.group(group) # self.logger.debug("Testing '%s' as a time string against '%s'" % (timeString, timeFormat)) if timeFormat == "%s": - ts = float(timeString) if len(timeString) < 10 else float(timeString) / (10**(len(timeString)-10)) + ts = float(timeString) if len(timeString) < 10 else float(timeString) \ + / (10**(len(timeString) - 10)) # self.logger.debug("Getting time for timestamp '%s'" % ts) currentTime = datetime.datetime.fromtimestamp(ts) else: - # self.logger.debugv("Getting time for timeFormat '%s' and timeString '%s'" % (timeFormat, timeString)) - # Working around Python bug with a non thread-safe strptime. Randomly get AttributeError + # self.logger.debug("Getting time for timeFormat '%s' and timeString '%s'" % + # (timeFormat, timeString)) + # Working around Python bug with a non thread-safe strptime. Randomly get AttributeError # when calling strptime, so if we get that, try again - while currentTime == None: + while currentTime is None: try: # Checking for timezone adjustment if timeString[-5] == "+": @@ -201,11 +208,13 @@ def getTSFromEvent(self, event, passed_token=None): if type(currentTime) == datetime.datetime: break except ValueError: - self.logger.warning("Match found ('%s') but time parse failed. Timeformat '%s' Event '%s'" % (timeString, timeFormat, event)) + self.logger.warning("Match found ('%s') but time parse failed. Timeformat '%s' Event '%s'" % + (timeString, timeFormat, event)) if type(currentTime) != datetime.datetime: # Total fail - if passed_token == None: # If we're running for autotimestamp don't log error - self.logger.warning("Can't find a timestamp (using patterns '%s') in this event: '%s'." % (formats, event)) + if passed_token is None: # If we're running for autotimestamp don't log error + self.logger.warning( + "Can't find a timestamp (using patterns '%s') in this event: '%s'." % (formats, event)) raise ValueError("Can't find a timestamp (using patterns '%s') in this event: '%s'." % (formats, event)) # Check to make sure we parsed a year if currentTime.year == 1900: @@ -216,18 +225,18 @@ def getTSFromEvent(self, event, passed_token=None): # if self.timestamp == None: # self.timestamp = currentTime return currentTime - + def saveState(self): """Saves state of all integer IDs of this sample to a file so when we restart we'll pick them up""" for token in self.tokens: if token.replacementType == 'integerid': - stateFile = open(os.path.join(self.sampleDir, 'state.'+urllib.pathname2url(token.token)), 'w') + stateFile = open(os.path.join(self.sampleDir, 'state.' + urllib.pathname2url(token.token)), 'w') stateFile.write(token.replacement) stateFile.close() def now(self, utcnow=False, realnow=False): # self.logger.info("Getting time (timezone %s)" % (self.timezone)) - if not self.backfilldone and not self.backfillts == None and not realnow: + if not self.backfilldone and self.backfillts is not None and not realnow: return self.backfillts elif self.timezone.days > 0: return datetime.datetime.now() @@ -246,11 +255,12 @@ def get_backfill_time(self, current_time): if self.backfill[-2:] == 'ms': time_unit = 'ms' backfill_time = self.backfill[1:-2] - return self.get_time_difference(current_time=current_time, different_time=backfill_time, sign='-', time_unit=time_unit) + return self.get_time_difference(current_time=current_time, different_time=backfill_time, sign='-', + time_unit=time_unit) else: self.logger.error("Backfill time is not in the past.") return current_time - + def get_time_difference(self, current_time, different_time, sign='-', time_unit='ms'): if time_unit == 'ms': return current_time + (int(sign + '1') * datetime.timedelta(milliseconds=int(different_time))) @@ -263,13 +273,10 @@ def get_time_difference(self, current_time, different_time, sign='-', time_unit= elif time_unit == 'd': return current_time + (int(sign + '1') * datetime.timedelta(days=int(different_time))) - - - def earliestTime(self): # First optimization, we need only store earliest and latest # as an offset of now if they're relative times - if self._earliestParsed != None: + if self._earliestParsed is not None: earliestTime = self.now() - self._earliestParsed self.logger.debug("Using cached earliest time: %s" % earliestTime) else: @@ -280,14 +287,16 @@ def earliestTime(self): temptd = self.now(realnow=True) - tempearliest self._earliestParsed = datetime.timedelta(days=temptd.days, seconds=temptd.seconds) earliestTime = self.now() - self._earliestParsed - self.logger.debug("Calulating earliestParsed as '%s' with earliestTime as '%s' and self.sample.earliest as '%s'" % (self._earliestParsed, earliestTime, tempearliest)) + self.logger.debug( + "Calulating earliestParsed as '%s' with earliestTime as '%s' and self.sample.earliest as '%s'" % + (self._earliestParsed, earliestTime, tempearliest)) else: earliestTime = timeParser(self.earliest, timezone=self.timezone) self.logger.debug("earliestTime as absolute time '%s'" % earliestTime) return earliestTime def latestTime(self): - if self._latestParsed != None: + if self._latestParsed is not None: latestTime = self.now() - self._latestParsed self.logger.debug("Using cached latestTime: %s" % latestTime) else: @@ -298,7 +307,9 @@ def latestTime(self): temptd = self.now(realnow=True) - templatest self._latestParsed = datetime.timedelta(days=temptd.days, seconds=temptd.seconds) latestTime = self.now() - self._latestParsed - self.logger.debug("Calulating latestParsed as '%s' with latestTime as '%s' and self.sample.latest as '%s'" % (self._latestParsed, latestTime, templatest)) + self.logger.debug( + "Calulating latestParsed as '%s' with latestTime as '%s' and self.sample.latest as '%s'" % + (self._latestParsed, latestTime, templatest)) else: latestTime = timeParser(self.latest, timezone=self.timezone) self.logger.debug("latstTime as absolute time '%s'" % latestTime) @@ -316,33 +327,36 @@ def _closeSampleFile(self): self._sampleFH.close() def loadSample(self): + """ + Load sample from disk into self._sample.sampleLines and self._sample.sampleDict, using cached copy if possible + """ if not self.logger: self._setup_logging() - """Load sample from disk into self._sample.sampleLines and self._sample.sampleDict, - using cached copy if possible""" if self.sampletype == 'raw': # 5/27/12 CS Added caching of the sample file - if self.sampleDict == None: + if self.sampleDict is None: self._openSampleFile() if self.breaker == self.config.breaker: self.logger.debug("Reading raw sample '%s' in app '%s'" % (self.name, self.app)) self.sampleLines = self._sampleFH.readlines() - # 1/5/14 CS Moving to using only sampleDict and doing the breaking up into events at load time instead of on every generation + # 1/5/14 CS Moving to using only sampleDict and doing the breaking up into events at load time instead + # of on every generation else: - self.logger.debug("Non-default breaker '%s' detected for sample '%s' in app '%s'" \ - % (self.breaker, self.name, self.app) ) + self.logger.debug("Non-default breaker '%s' detected for sample '%s' in app '%s'" % + (self.breaker, self.name, self.app)) sampleData = self._sampleFH.read() - self.sampleLines = [ ] + self.sampleLines = [] - self.logger.debug("Filling array for sample '%s' in app '%s'; sampleData=%s, breaker=%s" \ - % (self.name, self.app, len(sampleData), self.breaker)) + self.logger.debug("Filling array for sample '%s' in app '%s'; sampleData=%s, breaker=%s" % + (self.name, self.app, len(sampleData), self.breaker)) try: breakerRE = re.compile(self.breaker, re.M) except: - self.logger.error("Line breaker '%s' for sample '%s' in app '%s' could not be compiled; using default breaker" \ - % (self.breaker, self.name, self.app) ) + self.logger.error( + "Line breaker '%s' for sample '%s' in app '%s' could not be compiled; using default breaker" + % (self.breaker, self.name, self.app)) self.breaker = self.config.breaker # Loop through data, finding matches of the regular expression and breaking them up into @@ -365,14 +379,17 @@ def loadSample(self): for line in self.sampleLines: if line and line[-1] != '\n': line = line + '\n' - self.sampleDict.append({ '_raw': line, 'index': self.index, 'host': self.host, 'source': self.source, 'sourcetype': self.sourcetype }) - self.logger.debug('Finished creating sampleDict & sampleLines. Len samplesLines: %d Len sampleDict: %d' % (len(self.sampleLines), len(self.sampleDict))) + self.sampleDict.append({ + '_raw': line, 'index': self.index, 'host': self.host, 'source': self.source, 'sourcetype': + self.sourcetype}) + self.logger.debug('Finished creating sampleDict & sampleLines. Len samplesLines: %d Len sampleDict: %d' + % (len(self.sampleLines), len(self.sampleDict))) elif self.sampletype == 'csv': - if self.sampleDict == None: + if self.sampleDict is None: self._openSampleFile() self.logger.debug("Reading csv sample '%s' in app '%s'" % (self.name, self.app)) - self.sampleDict = [ ] - self.sampleLines = [ ] + self.sampleDict = [] + self.sampleLines = [] # Fix to load large csv files, work with python 2.5 onwards csv.field_size_limit(sys.maxint) csvReader = csv.DictReader(self._sampleFH) @@ -395,14 +412,29 @@ def loadSample(self): else: self.logger.error("Missing _raw in line '%s'" % pprint.pformat(line)) self._closeSampleFile() - self.logger.debug("Finished creating sampleDict & sampleLines for sample '%s'. Len sampleDict: %d" % (self.name, len(self.sampleDict))) + self.logger.debug("Finished creating sampleDict & sampleLines for sample '%s'. Len sampleDict: %d" % + (self.name, len(self.sampleDict))) for i in xrange(0, len(self.sampleDict)): if len(self.sampleDict[i]['_raw']) < 1 or self.sampleDict[i]['_raw'][-1] != '\n': self.sampleDict[i]['_raw'] += '\n' + if self.extendIndexes: + try: + for index_item in self.extendIndexes.split(','): + index_item = index_item.strip() + if ':' in index_item: + extend_indexes_count = int(index_item.split(':')[-1]) + extend_indexes_prefix = index_item.split(':')[0] + "{}" + self.index_list.extend([extend_indexes_prefix.format(_i) for _i in range(extend_indexes_count)]) + elif len(index_item): + self.index_list.append(index_item) + except Exception: + self.logger.error("Failed to parse extendIndexes, using index={} now.".format(self.index)) + self.index_list = [] + self.extendIndexes = None def get_loaded_sample(self): - if self.sampletype != 'csv' and os.path.getsize(self.filePath) > 10000000 : + if self.sampletype != 'csv' and os.path.getsize(self.filePath) > 10000000: self._openSampleFile() return self._sampleFH elif self.sampletype == 'csv': diff --git a/splunk_eventgen/lib/eventgentimer.py b/splunk_eventgen/lib/eventgentimer.py index 6079cbaa..364b9686 100644 --- a/splunk_eventgen/lib/eventgentimer.py +++ b/splunk_eventgen/lib/eventgentimer.py @@ -1,24 +1,26 @@ +import copy import logging import time -import copy -from timeparser import timeParserTimeMath from Queue import Full +from timeparser import timeParserTimeMath + + class Timer(object): """ - Overall governor in Eventgen. A timer is created for every sample in Eventgen. The Timer has the responsibility - for executing each sample. There are two ways the timer can execute: + Overall governor in Eventgen. A timer is created for every sample in Eventgen. The Timer has the responsibility + for executing each sample. There are two ways the timer can execute: * Queueable * Non-Queueable - For Queueable plugins, we place a work item in the generator queue. Generator workers pick up the item from the generator - queue and do work. This queueing architecture allows for parallel execution of workers. Workers then place items in the - output queue for Output workers to pick up and output. + For Queueable plugins, we place a work item in the generator queue. Generator workers pick up the item from the + generator queue and do work. This queueing architecture allows for parallel execution of workers. Workers then place + items in the output queue for Output workers to pick up and output. - However, for some generators, like the replay generator, we need to keep a single view of state of where we are in the replay. - This means we cannot generate items in parallel. This is why we also offer Non-Queueable plugins. In the case of - Non-Queueable plugins, the Timer class calls the generator method of the plugin directly, tracks the amount of time - the plugin takes to generate and sleeps the remaining interval before calling generate again. + However, for some generators, like the replay generator, we need to keep a single view of state of where we are in + the replay. This means we cannot generate items in parallel. This is why we also offer Non-Queueable plugins. In + the case of Non-Queueable plugins, the Timer class calls the generator method of the plugin directly, tracks the + amount of time the plugin takes to generate and sleeps the remaining interval before calling generate again. """ time = None countdown = None @@ -39,23 +41,23 @@ def __init__(self, time, sample=None, config=None, genqueue=None, outputqueue=No self.countdown = 0 self.executions = 0 self.interval = getattr(self.sample, "interval", config.interval) - #enable the logger self._setup_logging() self.logger.debug('Initializing timer for %s' % sample.name if sample is not None else "None") # load plugins - if self.sample != None: + if self.sample is not None: rater_class = self.config.getPlugin('rater.' + self.sample.rater, self.sample) self.rater = rater_class(self.sample) self.generatorPlugin = self.config.getPlugin('generator.' + self.sample.generator, self.sample) self.outputPlugin = self.config.getPlugin('output.' + self.sample.outputMode, self.sample) if self.sample.timeMultiple < 0: self.logger.error("Invalid setting for timeMultiple: {}, value should be positive".format( - self.sample.timeMultiple)) + self.sample.timeMultiple)) elif self.sample.timeMultiple != 1: self.interval = self.sample.interval * self.sample.timeMultiple self.logger.debug("Adjusting interval {} with timeMultiple {}, new interval: {}".format( - self.sample.interval, self.sample.timeMultiple, self.interval)) - self.logger.info("Start '%s' generatorWorkers for sample '%s'" % (self.sample.config.generatorWorkers, self.sample.name)) + self.sample.interval, self.sample.timeMultiple, self.interval)) + self.logger.info( + "Start '%s' generatorWorkers for sample '%s'" % (self.sample.config.generatorWorkers, self.sample.name)) # loggers can't be pickled due to the lock object, remove them before we try to pickle anything. def __getstate__(self): @@ -105,18 +107,20 @@ def real_run(self): end = False previous_count_left = 0 raw_event_size = self.predict_event_size() - if self.end and int(self.end) == 0: - self.logger.info("End = 0, no events will be generated for sample '%s'" % self.sample.name) - end = True + if self.end: + if int(self.end) == 0: + self.logger.info("End = 0, no events will be generated for sample '%s'" % self.sample.name) + end = True + elif int(self.end) == -1: + self.logger.info("End is set to -1. Will be running without stopping for sample %s" % self.sample.name) while not end: # Need to be able to stop threads by the main thread or this thread. self.config will stop all threads # referenced in the config object, while, self.stopping will only stop this one. if self.config.stopping or self.stopping: end = True count = self.rater.rate() - #First run of the generator, see if we have any backfill work to do. + # First run of the generator, see if we have any backfill work to do. if self.countdown <= 0: - if self.sample.backfill and not self.sample.backfilldone: realtime = self.sample.now(realnow=True) if "-" in self.sample.backfill[0]: @@ -130,34 +134,35 @@ def real_run(self): backfillnumber += char elif char != "-": backfillletter += char - backfillearliest = timeParserTimeMath(plusminus=mathsymbol, - num=backfillnumber, - unit=backfillletter, + backfillearliest = timeParserTimeMath(plusminus=mathsymbol, num=backfillnumber, unit=backfillletter, ret=realtime) while backfillearliest < realtime: + if self.executions == int(self.end): + self.logger.info("End executions %d reached, ending generation of sample '%s'" % (int( + self.end), self.sample.name)) + break et = backfillearliest lt = timeParserTimeMath(plusminus="+", num=self.interval, unit="s", ret=et) genPlugin = self.generatorPlugin(sample=self.sample) # need to make sure we set the queue right if we're using multiprocessing or thread modes genPlugin.updateConfig(config=self.config, outqueue=self.outputQueue) - genPlugin.updateCounts(count=count, - start_time=et, - end_time=lt) + genPlugin.updateCounts(count=count, start_time=et, end_time=lt) try: self.generatorQueue.put(genPlugin) + self.executions += 1 except Full: self.logger.warning("Generator Queue Full. Skipping current generation.") backfillearliest = lt + self.sample.backfilldone = True else: # 12/15/13 CS Moving the rating to a separate plugin architecture # Save previous interval count left to avoid perdayvolumegenerator drop small tasks if self.sample.generator == 'perdayvolumegenerator': count = self.rater.rate() + previous_count_left - if count < raw_event_size and count > 0: - self.logger.info( - "current interval size is {}, which is smaller than a raw event size {}. wait for the next turn.".format( - count, raw_event_size)) + if 0 < count < raw_event_size: + self.logger.info("current interval size is {}, which is smaller than a raw event size {}.". + format(count, raw_event_size) + "Wait for the next turn.") previous_count_left = count self.countdown = self.interval self.executions += 1 @@ -172,27 +177,33 @@ def real_run(self): try: if count < 1 and count != -1: - self.logger.info("There is no data to be generated in worker {0} because the count is {1}.".format(self.sample.config.generatorWorkers, count)) + self.logger.info( + "There is no data to be generated in worker {0} because the count is {1}.".format( + self.sample.config.generatorWorkers, count)) else: # Spawn workers at the beginning of job rather than wait for next interval - self.logger.info("Start '%d' generatorWorkers for sample '%s'" % ( - self.sample.config.generatorWorkers, self.sample.name)) + self.logger.info("Start '%d' generatorWorkers for sample '%s'" % + (self.sample.config.generatorWorkers, self.sample.name)) for worker_id in range(self.config.generatorWorkers): # self.generatorPlugin is only an instance, now we need a real plugin. Make a copy of # of the sample in case another generator corrupts it. copy_sample = copy.copy(self.sample) - tokens = copy.deepcopy(self.sample.tokens) - copy_sample.tokens = tokens + copy_tokens = [] + for token in self.sample.tokens: + copy_tokens.append(token.deepcopy(self.sample)) + copy_sample.tokens = copy_tokens genPlugin = self.generatorPlugin(sample=copy_sample) # Adjust queue for threading mode genPlugin.updateConfig(config=self.config, outqueue=self.outputQueue) - genPlugin.updateCounts(count=count, - start_time=et, - end_time=lt) + genPlugin.updateCounts(count=count, start_time=et, end_time=lt) try: self.generatorQueue.put(genPlugin) - self.logger.info("Worker# {0}: Put {1} MB of events in queue for sample '{2}' with et '{3}' and lt '{4}'".format(worker_id, round((count / 1024.0 / 1024), 4), self.sample.name, et, lt)) + self.executions += 1 + self.logger.info(("Worker# {0}: Put {1} MB of events in queue for sample '{2}'" + + "with et '{3}' and lt '{4}'").format( + worker_id, round((count / 1024.0 / 1024), 4), + self.sample.name, et, lt)) except Full: self.logger.warning("Generator Queue Full. Skipping current generation.") except Exception as e: @@ -203,24 +214,29 @@ def real_run(self): # Sleep until we're supposed to wake up and generate more events self.countdown = self.interval - self.executions += 1 # 8/20/15 CS Adding support for ending generation at a certain time + if self.end: + if int(self.end) == -1: + time.sleep(self.time) + self.countdown -= self.time + continue # 3/16/16 CS Adding support for ending on a number of executions instead of time # Should be fine with storing state in this sample object since each sample has it's own unique # timer thread if not self.endts: if self.executions >= int(self.end): - self.logger.info("End executions %d reached, ending generation of sample '%s'" % (int(self.end), self.sample.name)) + self.logger.info("End executions %d reached, ending generation of sample '%s'" % (int( + self.end), self.sample.name)) self.stopping = True end = True elif lt >= self.endts: - self.logger.info("End Time '%s' reached, ending generation of sample '%s'" % (self.sample.endts, self.sample.name)) + self.logger.info("End Time '%s' reached, ending generation of sample '%s'" % (self.sample.endts, + self.sample.name)) self.stopping = True end = True else: time.sleep(self.time) self.countdown -= self.time - diff --git a/splunk_eventgen/lib/eventgentimestamp.py b/splunk_eventgen/lib/eventgentimestamp.py index f42fb4d9..d1dca9e5 100644 --- a/splunk_eventgen/lib/eventgentimestamp.py +++ b/splunk_eventgen/lib/eventgentimestamp.py @@ -1,9 +1,9 @@ import datetime -import time import random +import time -class EventgenTimestamp(object): +class EventgenTimestamp(object): @staticmethod def get_random_timestamp(earliest, latest): if type(earliest) != datetime.datetime or type(latest) != datetime.datetime: @@ -23,7 +23,8 @@ def get_random_timestamp_backfill(earliest, latest, sample_earliest, sample_late earliest and latest timestamp gets generated with an interval sample_earliest and sample_latest are the user config key values from eventgen.conf we are using earliest as a pivot time and creating a random variance using sample_earliest and sample_latest. - in this way, we respect an interval passed in by a user and use user input earliest and latest to create a random variance + in this way, we respect an interval passed in by a user and use user input earliest and latest to create a + random variance. ''' if type(earliest) != datetime.datetime or type(latest) != datetime.datetime: raise Exception("Earliest {0} or latest {1} arguments are not datetime objects".format(earliest, latest)) @@ -50,7 +51,8 @@ def get_sequential_timestamp(earliest, latest, slot, total_slot): latest_in_epoch = time.mktime(latest.timetuple()) if earliest_in_epoch > latest_in_epoch: raise Exception("Latest time is earlier than earliest time.") - return datetime.datetime.fromtimestamp(earliest_in_epoch + (latest_in_epoch-earliest_in_epoch)*slot/total_slot) + return datetime.datetime.fromtimestamp(earliest_in_epoch + + (latest_in_epoch - earliest_in_epoch) * slot / total_slot) @staticmethod def _convert_time_difference_to_seconds(time_difference): diff --git a/splunk_eventgen/lib/eventgentoken.py b/splunk_eventgen/lib/eventgentoken.py index 9e883e05..d6c402fe 100644 --- a/splunk_eventgen/lib/eventgentoken.py +++ b/splunk_eventgen/lib/eventgentoken.py @@ -1,26 +1,29 @@ -# TODO Handle timestamp generation for modular input output where we set sample.timestamp properly when we do a timestamp replacement +# TODO: Handle timestamp generation for modinput and set sample.timestamp properly for timestamp replacement from __future__ import division, with_statement -import os + +import datetime +import json import logging +import os import pprint import random -import datetime, time import re -import json -import copy -from timeparser import timeParser, timeDelta2secs +import time import urllib import uuid +from timeparser import timeDelta2secs + + class Token(object): """Contains data and methods for replacing a token in a given sample""" token = None replacementType = None replacement = None sample = None - mvhash = { } - + mvhash = {} + _replaytd = None _lastts = None _tokenfile = None @@ -35,24 +38,21 @@ class Token(object): _stringMatch = None _listMatch = None _tokenfilecounter = 0 - + def __init__(self, sample=None): - + # Logger already setup by config, just get an instance self._setup_logging() - - if sample == None: - name = "None" - else: - name = sample.name - self._earliestTime = (None, None) self._latestTime = (None, None) - + + if sample: + self.sample = sample + def __str__(self): """Only used for debugging, outputs a pretty printed representation of this token""" # Eliminate recursive going back to parent - temp = dict([ (key, value) for (key, value) in self.__dict__.items() if key != 'sample' ]) + temp = dict([(key, value) for (key, value) in self.__dict__.items() if key != 'sample']) return pprint.pformat(temp) def __repr__(self): @@ -68,18 +68,26 @@ def __getstate__(self): def __setstate__(self, d): self.__dict__ = d self._setup_logging() + + def deepcopy(self, sample=None): + # temp = dict([(key, value) for (key, value) in token_object.items() if key != 'sample' and key != 'logger']) + cp = Token() + cp.__setstate__(self.__getstate__()) + if sample: + cp.sample = sample + return cp def _setup_logging(self): self.logger = logging.getLogger('eventgen') - + def _match(self, event): """Executes regular expression match and returns the re.Match object""" return re.match(self.token, event) - + def _search(self, event): """Executes regular expression search and returns the re.Match object""" return re.search(self.token, event) - + def _finditer(self, event): """Executes regular expression finditer and returns the re.Match object""" return re.finditer(self.token, event) @@ -87,7 +95,7 @@ def _finditer(self, event): def _findall(self, event): """Executes regular expression finditer and returns the re.Match object""" return re.findall(self.token, event) - + def replace(self, event, et=None, lt=None, s=None, pivot_timestamp=None): """Replaces all instances of this token in provided event and returns event""" if not getattr(self, 'logger', None): @@ -96,10 +104,11 @@ def replace(self, event, et=None, lt=None, s=None, pivot_timestamp=None): tokenMatch = list(self._finditer(event)) if len(tokenMatch) > 0: - replacement = self._getReplacement(event[tokenMatch[0].start(0):tokenMatch[0].end(0)], et, lt, s, pivot_timestamp=pivot_timestamp) + replacement = self._getReplacement(event[tokenMatch[0].start(0):tokenMatch[0].end(0)], et, lt, s, + pivot_timestamp=pivot_timestamp) if replacement is not None or self.replacementType == 'replaytimestamp': # logger.debug("Replacement: '%s'" % replacement) - ## Iterate matches + # Iterate matches for match in tokenMatch: # logger.debug("Match: %s" % (match)) try: @@ -131,8 +140,8 @@ def replace(self, event, et=None, lt=None, s=None, pivot_timestamp=None): self._replaytd = None self._lastts = None return event - - def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, pivot_timestamp=None): + + def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, pivot_timestamp=None): if self.replacementType == 'static': return self.replacement # This logic is done in replay.py @@ -141,86 +150,89 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, elif self.replacementType == 'timestamp': if s.earliest and s.latest: if earliestTime and latestTime: - if latestTime>=earliestTime: + if latestTime >= earliestTime: if pivot_timestamp: replacementTime = pivot_timestamp - elif s.timestamp == None: + elif s.timestamp is None: minDelta = 0 - ## Compute timeDelta as total_seconds + # Compute timeDelta as total_seconds td = latestTime - earliestTime if not type(td) == float: maxDelta = timeDelta2secs(td) else: maxDelta = td - ## Get random timeDelta - randomDelta = datetime.timedelta(seconds=random.randint(minDelta, maxDelta), microseconds=random.randint(0, latestTime.microsecond if latestTime.microsecond > 0 else 999999)) + # Get random timeDelta + randomDelta = datetime.timedelta( + seconds=random.randint(minDelta, maxDelta), microseconds=random.randint( + 0, latestTime.microsecond if latestTime.microsecond > 0 else 999999)) - ## Compute replacmentTime + # Compute replacmentTime replacementTime = latestTime - randomDelta s.timestamp = replacementTime else: replacementTime = s.timestamp - # logger.debug("Generating timestamp for sample '%s' with randomDelta %s, minDelta %s, maxDelta %s, earliestTime %s, latestTime %s, earliest: %s, latest: %s" % (s.name, randomDelta, minDelta, maxDelta, earliestTime, latestTime, s.earliest, s.latest)) - - replacement = self.replacement.replace('%s', str(round(time.mktime(replacementTime.timetuple()))).rstrip('0').rstrip('.')) + replacement = self.replacement.replace( + '%s', + str(round(time.mktime(replacementTime.timetuple()))).rstrip('0').rstrip('.')) replacementTime = replacementTime.strftime(replacement) - ## replacementTime == replacement for invalid strptime specifiers + # replacementTime == replacement for invalid strptime specifiers if replacementTime != self.replacement.replace('%', ''): return replacementTime else: - self.logger.error("Invalid strptime specifier '%s' detected; will not replace" \ - % (self.replacement) ) + self.logger.error( + "Invalid strptime specifier '%s' detected; will not replace" % (self.replacement)) return old - ## earliestTime/latestTime not proper + # earliestTime/latestTime not proper else: - self.logger.error("Earliest specifier '%s', value '%s' is greater than latest specifier '%s', value '%s' for sample '%s'; will not replace" \ - % (s.earliest, earliestTime, s.latest, latestTime, s.name) ) + self.logger.error(("Earliest specifier '%s', value '%s' is greater than latest specifier '%s'" + + "value '%s' for sample '%s'; will not replace") % + (s.earliest, earliestTime, s.latest, latestTime, s.name)) return old - ## earliest/latest not proper + # earliest/latest not proper else: self.logger.error('Earliest or latest specifier were not set; will not replace') return old elif self.replacementType in ('random', 'rated'): - ## Validations: - if self._integerMatch != None: + # Validations: + if self._integerMatch is not None: integerMatch = self._integerMatch else: integerRE = re.compile('integer\[([-]?\d+):([-]?\d+)\]', re.I) integerMatch = integerRE.match(self.replacement) self._integerMatch = integerMatch - - if self._floatMatch != None: + + if self._floatMatch is not None: floatMatch = self._floatMatch else: floatRE = re.compile('float\[(-?\d+|\d+\.(\d+)):(-?\d+|\d+\.(\d+))\]', re.I) floatMatch = floatRE.match(self.replacement) self._floatMatch = floatMatch - if self._stringMatch != None: + if self._stringMatch is not None: stringMatch = self._stringMatch else: stringRE = re.compile('string\((\d+)\)', re.I) stringMatch = stringRE.match(self.replacement) self._stringMatch = stringMatch - if self._hexMatch != None: + if self._hexMatch is not None: hexMatch = self._hexMatch - else: + else: hexRE = re.compile('hex\((\d+)\)', re.I) hexMatch = hexRE.match(self.replacement) self._hexMatch = hexMatch - if self._listMatch != None: + if self._listMatch is not None: listMatch = self._listMatch else: listRE = re.compile('list(\[[^\]]+\])', re.I) listMatch = listRE.match(self.replacement) self._listMatch = listMatch - ## Valid replacements: ipv4 | ipv6 | integer[:] | string() + # Valid replacements: ipv4 | ipv6 | integer[:] | string() if self.replacement.lower() == 'ipv4': x = 0 replacement = '' @@ -245,7 +257,7 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, x = 0 replacement = '' - ## Give me 6 blocks of 2 hex + # Give me 6 blocks of 2 hex while x < 6: y = 0 while y < 2: @@ -271,7 +283,7 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, rateFactor *= s.hourOfDayRate[str(s.now())] except KeyError: import traceback - stack = traceback.format_exc() + stack = traceback.format_exc() self.logger.error("Hour of day rate failed for token %s. Stacktrace %s" % stack) if type(s.dayOfWeekRate) == dict: try: @@ -283,13 +295,14 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, rateFactor *= s.dayOfWeekRate[str(weekday)] except KeyError: import traceback - stack = traceback.format_exc() + stack = traceback.format_exc() self.logger.error("Day of week rate failed. Stacktrace %s" % stack) replacementInt = int(round(replacementInt * rateFactor, 0)) replacement = str(replacementInt) return replacement else: - self.logger.error("Start integer %s greater than end integer %s; will not replace" % (startInt, endInt) ) + self.logger.error( + "Start integer %s greater than end integer %s; will not replace" % (startInt, endInt)) return old elif floatMatch: try: @@ -301,7 +314,7 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, significance = len(floatMatch.group(2)) if endFloat >= startFloat: - floatret = round(random.uniform(startFloat,endFloat), significance) + floatret = round(random.uniform(startFloat, endFloat), significance) if self.replacementType == 'rated': rateFactor = 1.0 now = s.now() @@ -310,7 +323,7 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, rateFactor *= s.hourOfDayRate[str(now.hour)] except KeyError: import traceback - stack = traceback.format_exc() + stack = traceback.format_exc() self.logger.error("Hour of day rate failed for token %s. Stacktrace %s" % stack) if type(s.dayOfWeekRate) == dict: try: @@ -322,13 +335,14 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, rateFactor *= s.dayOfWeekRate[str(weekday)] except KeyError: import traceback - stack = traceback.format_exc() + stack = traceback.format_exc() self.logger.error("Day of week rate failed. Stacktrace %s" % stack) floatret = round(floatret * rateFactor, significance) floatret = str(floatret) return floatret else: - self.logger.error("Start float %s greater than end float %s; will not replace" % (startFloat, endFloat)) + self.logger.error( + "Start float %s greater than end float %s; will not replace" % (startFloat, endFloat)) return old except ValueError: self.logger.error("Could not parse float[%s:%s]" % (floatMatch.group(1), floatMatch.group(4))) @@ -340,14 +354,16 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, elif strLength > 0: replacement = '' while len(replacement) < strLength: - ## Generate a random ASCII between dec 33->126 + # Generate a random ASCII between dec 33->126 replacement += chr(random.randint(33, 126)) - ## Practice safe strings + # Practice safe strings replacement = re.sub('%[0-9a-fA-F]+', '', urllib.quote(replacement)) - + return replacement else: - self.logger.error("Length specifier %s for string replacement must be greater than 0; will not replace" % (strLength) ) + self.logger.error( + "Length specifier %s for string replacement must be greater than 0; will not replace" % + (strLength)) return old elif hexMatch: strLength = int(hexMatch.group(1)) @@ -367,29 +383,32 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, return random.choice(value) else: - self.logger.error("Unknown replacement value '%s' for replacementType '%s'; will not replace" % (self.replacement, self.replacementType) ) + self.logger.error("Unknown replacement value '%s' for replacementType '%s'; will not replace" % + (self.replacement, self.replacementType)) return old elif self.replacementType in ('file', 'mvfile', 'seqfile'): - if self._replacementFile != None: + if self._replacementFile is not None: replacementFile = self._replacementFile replacementColumn = self._replacementColumn else: try: paths = self.replacement.split(':') - if(len(paths) == 1): + if (len(paths) == 1): replacementColumn = 0 else: - try: # When it's not a mvfile, there's no number on the end: + try: # When it's not a mvfile, there's no number on the end: replacementColumn = int(paths[-1]) except (ValueError): replacementColumn = 0 - if(replacementColumn > 0): + if (replacementColumn > 0): # This supports having a drive-letter colon replacementFile = s.pathParser(":".join(paths[0:-1])) else: replacementFile = s.pathParser(self.replacement) - except ValueError, e: - self.logger.error("Replacement string '%s' improperly formatted. Should be /path/to/file or /path/to/file:column" % (self.replacement)) + except ValueError: + self.logger.error( + "Replacement string '%s' improperly formatted. Should be /path/to/file or /path/to/file:column" + % self.replacement) return old self._replacementFile = replacementFile self._replacementColumn = replacementColumn @@ -399,18 +418,20 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, # return the same random pick on every iteration if replacementColumn > 0 and replacementFile in self.mvhash: if replacementColumn > len(self.mvhash[replacementFile]): - self.logger.error("Index for column '%s' in replacement file '%s' is out of bounds" % (replacementColumn, replacementFile)) + self.logger.error("Index for column '%s' in replacement file '%s' is out of bounds" % + (replacementColumn, replacementFile)) return old else: # self.logger.debug("Returning mvhash: %s" % self.mvhash[replacementFile][replacementColumn-1]) - return self.mvhash[replacementFile][replacementColumn-1] + return self.mvhash[replacementFile][replacementColumn - 1] else: # Adding caching of the token file to avoid reading it every iteration - if self._tokenfile != None: + if self._tokenfile is not None: replacementLines = self._tokenfile - ## Otherwise, lets read the file and build our cached results, pick a result and return it + # Otherwise, lets read the file and build our cached results, pick a result and return it else: - # self.logger.debug("replacementFile: %s replacementColumn: %s" % (replacementFile, replacementColumn)) + # self.logger.debug("replacementFile: %s replacementColumn: %s" % + # (replacementFile, replacementColumn)) replacementFile = os.path.abspath(replacementFile) self.logger.debug("Normalized replacement file %s" % replacementFile) if os.path.exists(replacementFile) and os.path.isfile(replacementFile): @@ -419,7 +440,7 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, replacementFH.close() if len(replacementLines) == 0: - self.logger.error("Replacement file '%s' is empty; will not replace" % (replacementFile) ) + self.logger.error("Replacement file '%s' is empty; will not replace" % (replacementFile)) return old else: self._tokenfile = replacementLines @@ -432,16 +453,17 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, self._tokenfilecounter += 1 else: # pick value randomly from replacement file - replacement = replacementLines[random.randint(0, len(replacementLines)-1)].strip() + replacement = replacementLines[random.randint(0, len(replacementLines) - 1)].strip() if replacementColumn > 0: self.mvhash[replacementFile] = replacement.split(',') if replacementColumn > len(self.mvhash[replacementFile]): - self.logger.error("Index for column '%s' in replacement file '%s' is out of bounds" % (replacementColumn, replacementFile)) + self.logger.error("Index for column '%s' in replacement file '%s' is out of bounds" % + (replacementColumn, replacementFile)) return old else: - return self.mvhash[replacementFile][replacementColumn-1] + return self.mvhash[replacementFile][replacementColumn - 1] else: return replacement elif self.replacementType == 'integerid': @@ -450,5 +472,5 @@ def _getReplacement(self, old=None, earliestTime=None, latestTime=None, s=None, return temp else: - self.logger.error("Unknown replacementType '%s'; will not replace" % (self.replacementType) ) - return old \ No newline at end of file + self.logger.error("Unknown replacementType '%s'; will not replace" % self.replacementType) + return old diff --git a/splunk_eventgen/lib/generatorplugin.py b/splunk_eventgen/lib/generatorplugin.py index ebca83a2..6ab1ecac 100644 --- a/splunk_eventgen/lib/generatorplugin.py +++ b/splunk_eventgen/lib/generatorplugin.py @@ -1,15 +1,21 @@ from __future__ import division + +import datetime import logging import logging.handlers import pprint -import datetime -from timeparser import timeParser -import httplib2, urllib +import time +import random +import urllib from xml.dom import minidom from xml.parsers.expat import ExpatError + +import httplib2 + from eventgenoutput import Output from eventgentimestamp import EventgenTimestamp -import time +from timeparser import timeParser + class GeneratorPlugin(object): sampleLines = None @@ -22,7 +28,7 @@ def __init__(self, sample): def __str__(self): """Only used for debugging, outputs a pretty printed representation of this output""" # Eliminate recursive going back to parent - temp = dict([ (key, value) for (key, value) in self.__dict__.items() if key != '_c']) + # temp = dict([(key, value) for (key, value) in self.__dict__.items() if key != '_c']) # return pprint.pformat(temp) return "" @@ -56,8 +62,8 @@ def build_events(self, eventsDict, startTime, earliest, latest, ignore_tokens=Fa timeDiffFrac = "%d.%06d" % (timeDiff.seconds, timeDiff.microseconds) self.logger.debug("Interval complete, flushing feed") self._out.flush(endOfInterval=True) - self.logger.debug("Generation of sample '%s' in app '%s' completed in %s seconds." % ( - self._sample.name, self._sample.app, timeDiffFrac)) + self.logger.debug("Generation of sample '%s' in app '%s' completed in %s seconds." % + (self._sample.name, self._sample.app, timeDiffFrac)) except Exception as e: self.logger.exception("Exception {} happened.".format(type(e))) raise e @@ -81,60 +87,66 @@ def updateConfig(self, config, outqueue): def updateCounts(self, sample=None, count=None, start_time=None, end_time=None): if sample: - self._sample=sample + self._sample = sample self.count = count self.start_time = start_time self.end_time = end_time def setOutputMetadata(self, event): - # self.logger.debug("Sample Index: %s Host: %s Source: %s Sourcetype: %s" % (self.index, self.host, self.source, self.sourcetype)) - # self.logger.debug("Event Index: %s Host: %s Source: %s Sourcetype: %s" % (sampleDict[x]['index'], sampleDict[x]['host'], sampleDict[x]['source'], sampleDict[x]['sourcetype'])) - if self._sample.sampletype == 'csv' and (event['index'] != self._sample.index or - event['host'] != self._sample.host or - event['source'] != self._sample.source or - event['sourcetype'] != self._sample.sourcetype): + # self.logger.debug("Sample Index: %s Host: %s Source: %s Sourcetype: %s" % + # (self.index, self.host, self.source, self.sourcetype)) + # self.logger.debug("Event Index: %s Host: %s Source: %s Sourcetype: %s" % + # (sampleDict[x]['index'], sampleDict[x]['host'], sampleDict[x]['source'], + # sampleDict[x]['sourcetype'])) + if self._sample.sampletype == 'csv' and (event['index'] != self._sample.index + or event['host'] != self._sample.host + or event['source'] != self._sample.source + or event['sourcetype'] != self._sample.sourcetype): self._sample.index = event['index'] self._sample.host = event['host'] # Allow randomizing the host: - if(self._sample.hostToken): + if self._sample.hostToken: self.host = self._sample.hostToken.replace(self.host) self._sample.source = event['source'] self._sample.sourcetype = event['sourcetype'] - self.logger.debugv("Sampletype CSV. Setting CSV parameters. index: '%s' host: '%s' source: '%s' sourcetype: '%s'" \ - % (self._sample.index, self._sample.host, self._sample.source, self._sample.sourcetype)) + self.logger.debug("Setting CSV parameters. index: '%s' host: '%s' source: '%s' sourcetype: '%s'" % + (self._sample.index, self._sample.host, self._sample.source, self._sample.sourcetype)) def setupBackfill(self): - """Called by non-queueable plugins or by the timer to setup backfill times per config or based on a Splunk Search""" + """ + Called by non-queueable plugins or by the timer to setup backfill times per config or based on a Splunk Search + """ s = self._sample - if s.backfill != None: + if s.backfill is not None: try: s.backfillts = timeParser(s.backfill, timezone=s.timezone) - self.logger.info("Setting up backfill of %s (%s)" % (s.backfill,s.backfillts)) + self.logger.info("Setting up backfill of %s (%s)" % (s.backfill, s.backfillts)) except Exception as ex: self.logger.error("Failed to parse backfill '%s': %s" % (s.backfill, ex)) raise - if s.backfillSearch != None: - if s.backfillSearchUrl == None: + if s.backfillSearch is not None: + if s.backfillSearchUrl is None: try: - s.backfillSearchUrl = c.getSplunkUrl(s)[0] + s.backfillSearchUrl = c.getSplunkUrl(s)[0] # noqa, we update c in the globals() dict except ValueError: - self.logger.error("Backfill Search URL not specified for sample '%s', not running backfill search" % s.name) + self.logger.error( + "Backfill Search URL not specified for sample '%s', not running backfill search" % s.name) if not s.backfillSearch.startswith('search'): s.backfillSearch = 'search ' + s.backfillSearch s.backfillSearch += '| head 1 | table _time' - if s.backfillSearchUrl != None: - self.logger.debug("Searching Splunk URL '%s/services/search/jobs' with search '%s' with sessionKey '%s'" % (s.backfillSearchUrl, s.backfillSearch, s.sessionKey)) - + if s.backfillSearchUrl is not None: + self.logger.debug( + "Searching Splunk URL '%s/services/search/jobs' with search '%s' with sessionKey '%s'" % + (s.backfillSearchUrl, s.backfillSearch, s.sessionKey)) + results = httplib2.Http(disable_ssl_certificate_validation=True).request( - s.backfillSearchUrl + '/services/search/jobs', - 'POST', headers={'Authorization': 'Splunk %s' % s.sessionKey}, - body=urllib.urlencode({'search': s.backfillSearch, - 'earliest_time': s.backfill, - 'exec_mode': 'oneshot'}))[1] + s.backfillSearchUrl + '/services/search/jobs', 'POST', headers={ + 'Authorization': 'Splunk %s' % s.sessionKey}, body=urllib.urlencode({ + 'search': s.backfillSearch, 'earliest_time': s.backfill, 'exec_mode': 'oneshot'}))[1] try: temptime = minidom.parseString(results).getElementsByTagName('text')[0].childNodes[0].nodeValue # self.logger.debug("Time returned from backfill search: %s" % temptime) @@ -145,8 +157,9 @@ def setupBackfill(self): temptime = temptime.split('+')[0] temptime = '-'.join(temptime.split('-')[0:3]) s.backfillts = datetime.datetime.strptime(temptime, '%Y-%m-%dT%H:%M:%S.%f') - self.logger.debug("Backfill search results: '%s' value: '%s' time: '%s'" % (pprint.pformat(results), temptime, s.backfillts)) - except (ExpatError, IndexError): + self.logger.debug("Backfill search results: '%s' value: '%s' time: '%s'" % + (pprint.pformat(results), temptime, s.backfillts)) + except (ExpatError, IndexError): pass if s.end is not None: @@ -157,13 +170,14 @@ def setupBackfill(self): parsed = True except ValueError: self.logger.debug("Failed to parse end '%s' for sample '%s', treating as end time" % (s.end, s.name)) - - if not parsed: + + if not parsed: try: s.endts = timeParser(s.end, timezone=s.timezone) self.logger.info("Ending generation at %s (%s)" % (s.end, s.endts)) except Exception as ex: - self.logger.error("Failed to parse end '%s' for sample '%s', treating as number of executions" % (s.end, s.name)) + self.logger.error( + "Failed to parse end '%s' for sample '%s', treating as number of executions" % (s.end, s.name)) raise def run(self, output_counter=None): @@ -189,7 +203,7 @@ def replace_tokens(self, eventsDict, earliest, latest, ignore_tokens=False): mvhash = {} host = targetevent['host'] if hasattr(self._sample, "sequentialTimestamp") and self._sample.sequentialTimestamp and \ - self._sample.generator != 'perdayvolumegenerator': + self._sample.generator != 'perdayvolumegenerator': pivot_timestamp = EventgenTimestamp.get_sequential_timestamp(earliest, latest, eventcount, total_count) else: pivot_timestamp = EventgenTimestamp.get_random_timestamp(earliest, latest) @@ -212,14 +226,10 @@ def replace_tokens(self, eventsDict, earliest, latest, ignore_tokens=False): time_val = int(time.mktime(pivot_timestamp.timetuple())) except Exception: time_val = int(time.mktime(self._sample.now().timetuple())) - l = {'_raw': event, - 'index': targetevent['index'], - 'host': host, - 'hostRegex': self._sample.hostRegex, - 'source': targetevent['source'], - 'sourcetype': targetevent['sourcetype'], - '_time': time_val} - send_events.append(l) + temp_event = { + '_raw': event, 'index': random.choice(self._sample.index_list)if len(self._sample.index_list) else targetevent['index'], 'host': host, 'hostRegex': self._sample.hostRegex, + 'source': targetevent['source'], 'sourcetype': targetevent['sourcetype'], '_time': time_val} + send_events.append(temp_event) return send_events diff --git a/splunk_eventgen/lib/logutils_src/doc/conf.py b/splunk_eventgen/lib/logutils_src/doc/conf.py index 2f89fe54..17a8499c 100644 --- a/splunk_eventgen/lib/logutils_src/doc/conf.py +++ b/splunk_eventgen/lib/logutils_src/doc/conf.py @@ -14,7 +14,8 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import os +import sys # If your extensions (or modules documented by autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -35,7 +36,7 @@ source_suffix = '.rst' # The encoding of source files. -#source_encoding = 'utf-8' +# source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' @@ -55,39 +56,38 @@ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. -#unused_docs = [] +# unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' - # Options for HTML output # ----------------------- @@ -98,19 +98,19 @@ # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -119,38 +119,38 @@ # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_use_modindex = True +# html_use_modindex = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, the reST sources are included in the HTML build as _sources/. -#html_copy_source = True +# html_copy_source = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' +# html_file_suffix = '' html_theme = os.environ.get('DOCS_THEME', 'alabaster') html_theme_path = ['themes'] @@ -158,42 +158,37 @@ # Output file base name for HTML help builder. htmlhelp_basename = 'Logutilsdoc' - # Options for LaTeX output # ------------------------ # The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' +# latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' +# latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, document class [howto/manual]). latex_documents = [ - ('index', 'Logutils.tex', ur'Logutils Documentation', - ur'Vinay Sajip', 'manual'), -] + ('index', 'Logutils.tex', ur'Logutils Documentation', ur'Vinay Sajip', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # Additional stuff for the LaTeX preamble. -#latex_preamble = '' +# latex_preamble = '' # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_use_modindex = True - +# latex_use_modindex = True # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { - 'http://docs.python.org/dev': None, -} + 'http://docs.python.org/dev': None, } diff --git a/splunk_eventgen/lib/logutils_src/logutils/__init__.py b/splunk_eventgen/lib/logutils_src/logutils/__init__.py index 963c8df4..2811a987 100644 --- a/splunk_eventgen/lib/logutils_src/logutils/__init__.py +++ b/splunk_eventgen/lib/logutils_src/logutils/__init__.py @@ -15,6 +15,7 @@ __version__ = '0.3.4.1' + class NullHandler(logging.Handler): """ This handler does nothing. It's intended to be used to avoid the @@ -48,6 +49,7 @@ def createLock(self): """ self.lock = None + class PercentStyle(object): default_format = '%(message)s' @@ -62,6 +64,7 @@ def usesTime(self): def format(self, record): return self._fmt % record.__dict__ + class StrFormatStyle(PercentStyle): default_format = '{message}' asctime_format = '{asctime}' @@ -85,11 +88,9 @@ def usesTime(self): def format(self, record): return self._tpl.substitute(**record.__dict__) -_STYLES = { - '%': PercentStyle, - '{': StrFormatStyle, - '$': StringTemplateStyle -} + +_STYLES = {'%': PercentStyle, '{': StrFormatStyle, '$': StringTemplateStyle} + class Formatter(logging.Formatter): """ @@ -97,6 +98,7 @@ class Formatter(logging.Formatter): 3.2 Formatter behaviour with respect to allowing %-, {} or $- formatting. """ + def __init__(self, fmt=None, datefmt=None, style='%'): """ Initialize the formatter with specified format strings. @@ -110,8 +112,7 @@ def __init__(self, fmt=None, datefmt=None, style='%'): :class:`string.Template` formatting in your format string. """ if style not in _STYLES: - raise ValueError('Style must be one of: %s' % ','.join( - _STYLES.keys())) + raise ValueError('Style must be one of: %s' % ','.join(_STYLES.keys())) self._style = _STYLES[style](fmt) self._fmt = self._style._fmt self.datefmt = datefmt @@ -166,6 +167,7 @@ def __str__(self): self.str = self.fmt.format(*self.args, **self.kwargs) return self.str + class DollarMessage(object): def __init__(self, fmt, **kwargs): self.fmt = fmt diff --git a/splunk_eventgen/lib/logutils_src/logutils/adapter.py b/splunk_eventgen/lib/logutils_src/logutils/adapter.py index 92706c0f..220c188d 100644 --- a/splunk_eventgen/lib/logutils_src/logutils/adapter.py +++ b/splunk_eventgen/lib/logutils_src/logutils/adapter.py @@ -2,8 +2,10 @@ # Copyright (C) 2010-2017 Vinay Sajip. See LICENSE.txt for details. # import logging + import logutils + class LoggerAdapter(object): """ An adapter for loggers which makes it easier to specify contextual diff --git a/splunk_eventgen/lib/logutils_src/logutils/colorize.py b/splunk_eventgen/lib/logutils_src/logutils/colorize.py index f95c0366..8f375e5d 100644 --- a/splunk_eventgen/lib/logutils_src/logutils/colorize.py +++ b/splunk_eventgen/lib/logutils_src/logutils/colorize.py @@ -10,6 +10,7 @@ except NameError: unicode = None + class ColorizingStreamHandler(logging.StreamHandler): """ A stream handler which supports colorizing of console streams @@ -28,18 +29,16 @@ class ColorizingStreamHandler(logging.StreamHandler): 'blue': 4, 'magenta': 5, 'cyan': 6, - 'white': 7, - } + 'white': 7, } - #levels to (background, foreground, bold/intense) + # levels to (background, foreground, bold/intense) if os.name == 'nt': level_map = { logging.DEBUG: (None, 'blue', True), logging.INFO: (None, 'white', False), logging.WARNING: (None, 'yellow', True), logging.ERROR: (None, 'red', True), - logging.CRITICAL: ('red', 'white', True), - } + logging.CRITICAL: ('red', 'white', True), } else: "Maps levels to colour/intensity settings." level_map = { @@ -47,8 +46,7 @@ class ColorizingStreamHandler(logging.StreamHandler): logging.INFO: (None, 'black', False), logging.WARNING: (None, 'yellow', False), logging.ERROR: (None, 'red', False), - logging.CRITICAL: ('red', 'white', True), - } + logging.CRITICAL: ('red', 'white', True), } csi = '\x1b[' reset = '\x1b[0m' @@ -78,6 +76,7 @@ def emit(self, record): self.handleError(record) if os.name != 'nt': + def output_colorized(self, message): """ Output a colorized message. @@ -98,14 +97,14 @@ def output_colorized(self, message): ansi_esc = re.compile(r'\x1b\[((?:\d+)(?:;(?:\d+))*)m') nt_color_map = { - 0: 0x00, # black - 1: 0x04, # red - 2: 0x02, # green - 3: 0x06, # yellow - 4: 0x01, # blue - 5: 0x05, # magenta - 6: 0x03, # cyan - 7: 0x07, # white + 0: 0x00, # black + 1: 0x04, # red + 2: 0x02, # green + 3: 0x06, # yellow + 4: 0x01, # blue + 5: 0x05, # magenta + 6: 0x03, # cyan + 7: 0x07, # white } def output_colorized(self, message): @@ -128,7 +127,7 @@ def output_colorized(self, message): fd = getattr(self.stream, 'fileno', None) if fd is not None: fd = fd() - if fd in (1, 2): # stdout or stderr + if fd in (1, 2): # stdout or stderr h = ctypes.windll.kernel32.GetStdHandle(-10 - fd) while parts: text = parts.pop(0) @@ -145,11 +144,11 @@ def output_colorized(self, message): elif 30 <= p <= 37: color |= self.nt_color_map[p - 30] elif p == 1: - color |= 0x08 # foreground intensity on - elif p == 0: # reset to default color + color |= 0x08 # foreground intensity on + elif p == 0: # reset to default color color = 0x07 else: - pass # error condition ignored + pass # error condition ignored ctypes.windll.kernel32.SetConsoleTextAttribute(h, color) def colorize(self, message, record): @@ -173,8 +172,7 @@ def colorize(self, message, record): if bold: params.append('1') if params: - message = ''.join((self.csi, ';'.join(params), - 'm', message, self.reset)) + message = ''.join((self.csi, ';'.join(params), 'm', message, self.reset)) return message def format(self, record): diff --git a/splunk_eventgen/lib/logutils_src/logutils/dictconfig.py b/splunk_eventgen/lib/logutils_src/logutils/dictconfig.py index c774552e..26b8886e 100644 --- a/splunk_eventgen/lib/logutils_src/logutils/dictconfig.py +++ b/splunk_eventgen/lib/logutils_src/logutils/dictconfig.py @@ -4,7 +4,6 @@ import logging.handlers import re import sys -import types try: basestring @@ -17,18 +16,21 @@ IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I) + def valid_ident(s): m = IDENTIFIER.match(s) if not m: raise ValueError('Not a valid Python identifier: %r' % s) return True + # # This function is defined in logging only in recent versions of Python # try: from logging import _checkLevel except ImportError: + def _checkLevel(level): if isinstance(level, int): rv = level @@ -41,10 +43,10 @@ def _checkLevel(level): raise ValueError('Unknown level: %r' % level) rv = levelnames[level] else: - raise TypeError('Level not an integer or a ' - 'valid string: %r' % level) + raise TypeError('Level not an integer or a ' 'valid string: %r' % level) return rv + # The ConvertingXXX classes are wrappers around standard Python containers, # and they serve to convert any suitable values in the container. The # conversion converts base dicts, lists and tuples to their wrapped @@ -54,17 +56,17 @@ def _checkLevel(level): # Each wrapper should have a configurator attribute holding the actual # configurator to use for conversion. + class ConvertingDict(dict): """A converting dictionary wrapper.""" def __getitem__(self, key): value = dict.__getitem__(self, key) result = self.configurator.convert(value) - #If the converted value is different, save for next time + # If the converted value is different, save for next time if value is not result: self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): + if type(result) in (ConvertingDict, ConvertingList, ConvertingTuple): result.parent = self result.key = key return result @@ -72,11 +74,10 @@ def __getitem__(self, key): def get(self, key, default=None): value = dict.get(self, key, default) result = self.configurator.convert(value) - #If the converted value is different, save for next time + # If the converted value is different, save for next time if value is not result: self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): + if type(result) in (ConvertingDict, ConvertingList, ConvertingTuple): result.parent = self result.key = key return result @@ -85,22 +86,22 @@ def pop(self, key, default=None): value = dict.pop(self, key, default) result = self.configurator.convert(value) if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): + if type(result) in (ConvertingDict, ConvertingList, ConvertingTuple): result.parent = self result.key = key return result + class ConvertingList(list): """A converting list wrapper.""" + def __getitem__(self, key): value = list.__getitem__(self, key) result = self.configurator.convert(value) - #If the converted value is different, save for next time + # If the converted value is different, save for next time if value is not result: self[key] = result - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): + if type(result) in (ConvertingDict, ConvertingList, ConvertingTuple): result.parent = self result.key = key return result @@ -109,23 +110,24 @@ def pop(self, idx=-1): value = list.pop(self, idx) result = self.configurator.convert(value) if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): + if type(result) in (ConvertingDict, ConvertingList, ConvertingTuple): result.parent = self return result + class ConvertingTuple(tuple): """A converting tuple wrapper.""" + def __getitem__(self, key): value = tuple.__getitem__(self, key) result = self.configurator.convert(value) if value is not result: - if type(result) in (ConvertingDict, ConvertingList, - ConvertingTuple): + if type(result) in (ConvertingDict, ConvertingList, ConvertingTuple): result.parent = self result.key = key return result + class BaseConfigurator(object): """ The configurator base class which defines some useful defaults. @@ -139,9 +141,8 @@ class BaseConfigurator(object): DIGIT_PATTERN = re.compile(r'^\d+$') value_converters = { - 'ext' : 'ext_convert', - 'cfg' : 'cfg_convert', - } + 'ext': 'ext_convert', + 'cfg': 'cfg_convert', } # We might want to use a different one, e.g. importlib importer = __import__ @@ -191,7 +192,6 @@ def cfg_convert(self, value): else: rest = rest[m.end():] d = self.config[m.groups()[0]] - #print d, rest while rest: m = self.DOT_PATTERN.match(rest) if m: @@ -204,16 +204,15 @@ def cfg_convert(self, value): d = d[idx] else: try: - n = int(idx) # try as number first (most likely) + n = int(idx) # try as number first (most likely) d = d[n] except TypeError: d = d[idx] if m: rest = rest[m.end():] else: - raise ValueError('Unable to convert ' - '%r at %r' % (value, rest)) - #rest should be empty + raise ValueError('Unable to convert ' '%r at %r' % (value, rest)) + # rest should be empty return d def convert(self, value): @@ -228,8 +227,7 @@ def convert(self, value): elif not isinstance(value, ConvertingList) and isinstance(value, list): value = ConvertingList(value) value.configurator = self - elif not isinstance(value, ConvertingTuple) and\ - isinstance(value, tuple): + elif not isinstance(value, ConvertingTuple) and isinstance(value, tuple): value = ConvertingTuple(value) value.configurator = self elif isinstance(value, basestring): @@ -264,6 +262,7 @@ def as_tuple(self, value): value = tuple(value) return value + def named_handlers_supported(): major, minor = sys.version_info[:2] if major == 2: @@ -274,6 +273,7 @@ def named_handlers_supported(): result = (major > 3) return result + class DictConfigurator(BaseConfigurator): """ Configure logging using a dictionary-like object to describe the @@ -299,8 +299,7 @@ def configure(self): if named_handlers_supported(): for name in handlers: if name not in logging._handlers: - raise ValueError('No handler found with ' - 'name %r' % name) + raise ValueError('No handler found with ' 'name %r' % name) else: try: handler = logging._handlers[name] @@ -310,24 +309,21 @@ def configure(self): handler.setLevel(_checkLevel(level)) except StandardError: e = sys.exc_info()[1] - raise ValueError('Unable to configure handler ' - '%r: %s' % (name, e)) + raise ValueError('Unable to configure handler ' '%r: %s' % (name, e)) loggers = config.get('loggers', EMPTY_DICT) for name in loggers: try: self.configure_logger(name, loggers[name], True) except StandardError: e = sys.exc_info()[1] - raise ValueError('Unable to configure logger ' - '%r: %s' % (name, e)) + raise ValueError('Unable to configure logger ' '%r: %s' % (name, e)) root = config.get('root', None) if root: try: self.configure_root(root, True) except StandardError: e = sys.exc_info()[1] - raise ValueError('Unable to configure root ' - 'logger: %s' % e) + raise ValueError('Unable to configure root ' 'logger: %s' % e) else: disable_existing = config.pop('disable_existing_loggers', True) @@ -338,12 +334,10 @@ def configure(self): formatters = config.get('formatters', EMPTY_DICT) for name in formatters: try: - formatters[name] = self.configure_formatter( - formatters[name]) + formatters[name] = self.configure_formatter(formatters[name]) except StandardError: e = sys.exc_info()[1] - raise ValueError('Unable to configure ' - 'formatter %r: %s' % (name, e)) + raise ValueError('Unable to configure ' 'formatter %r: %s' % (name, e)) # Next, do filters - they don't refer to anything else, either filters = config.get('filters', EMPTY_DICT) for name in filters: @@ -351,8 +345,7 @@ def configure(self): filters[name] = self.configure_filter(filters[name]) except StandardError: e = sys.exc_info()[1] - raise ValueError('Unable to configure ' - 'filter %r: %s' % (name, e)) + raise ValueError('Unable to configure ' 'filter %r: %s' % (name, e)) # Next, do handlers - they refer to formatters and filters # As handlers can refer to other handlers, sort the keys @@ -365,28 +358,20 @@ def configure(self): handlers[name] = handler except StandardError: e = sys.exc_info()[1] - raise ValueError('Unable to configure handler ' - '%r: %s' % (name, e)) + raise ValueError('Unable to configure handler ' '%r: %s' % (name, e)) # Next, do loggers - they refer to handlers and filters - #we don't want to lose the existing loggers, - #since other threads may have pointers to them. - #existing is set to contain all existing loggers, - #and as we go through the new configuration we - #remove any which are configured. At the end, - #what's left in existing is the set of loggers - #which were in the previous configuration but - #which are not in the new configuration. + # We don't want to lose the existing loggers, since other threads may have pointers to them. + # Existing is set to contain all existing loggers, and as we go through the new configuration we + # remove any which are configured. At the end, what's left in existing is the set of loggers + # which were in the previous configuration but which are not in the new configuration. root = logging.root existing = sorted(root.manager.loggerDict.keys()) - #The list needs to be sorted so that we can - #avoid disabling child loggers of explicitly - #named loggers. With a sorted list it is easier - #to find the child loggers. - #We'll keep the list of existing loggers - #which are children of named loggers here... + # The list needs to be sorted so that we can avoid disabling child loggers of explicitly named loggers. + # With a sorted list it is easier to find the child loggers. We'll keep the list of existing loggers + # which are children of named loggers here... child_loggers = [] - #now set up the new ones... + # now set up the new ones... loggers = config.get('loggers', EMPTY_DICT) for name in loggers: if name in existing: @@ -394,7 +379,7 @@ def configure(self): prefixed = name + "." pflen = len(prefixed) num_existing = len(existing) - i = i + 1 # look at the entry after name + i = i + 1 # look at the entry after name while (i < num_existing) and\ (existing[i][:pflen] == prefixed): child_loggers.append(existing[i]) @@ -404,14 +389,11 @@ def configure(self): self.configure_logger(name, loggers[name]) except StandardError: e = sys.exc_info()[1] - raise ValueError('Unable to configure logger ' - '%r: %s' % (name, e)) - - #Disable any old loggers. There's no point deleting - #them as other threads may continue to hold references - #and by disabling them, you stop them doing any logging. - #However, don't disable children of named loggers, as that's - #probably not what was intended by the user. + raise ValueError('Unable to configure logger ' '%r: %s' % (name, e)) + + # Disable any old loggers. There's no point deleting them as other threads may continue to hold + # references and by disabling them, you stop them doing any logging. However, don't disable children of + # named loggers, as that's probably not what was intended by the user. for log in existing: logger = root.manager.loggerDict[log] if log in child_loggers: @@ -428,25 +410,22 @@ def configure(self): self.configure_root(root) except StandardError: e = sys.exc_info()[1] - raise ValueError('Unable to configure root ' - 'logger: %s' % e) + raise ValueError('Unable to configure root ' 'logger: %s' % e) finally: logging._releaseLock() def configure_formatter(self, config): """Configure a formatter from a dictionary.""" if '()' in config: - factory = config['()'] # for use in exception handler + factory = config['()'] # for use in exception handler try: result = self.configure_custom(config) except TypeError: te = sys.exc_info()[1] if "'format'" not in str(te): raise - #Name of parameter changed from fmt to format. - #Retry with old name. - #This is so that code can be used with older Python versions - #(e.g. by Django) + # Name of parameter changed from fmt to format. Retry with old name. This is so that code can be used + # with older Python versions (e.g. by Django) config['fmt'] = config.pop('format') config['()'] = factory result = self.configure_custom(config) @@ -482,8 +461,7 @@ def configure_handler(self, config): formatter = self.config['formatters'][formatter] except StandardError: e = sys.exc_info()[1] - raise ValueError('Unable to set formatter ' - '%r: %s' % (formatter, e)) + raise ValueError('Unable to set formatter ' '%r: %s' % (formatter, e)) level = config.pop('level', None) filters = config.pop('filters', None) if '()' in config: @@ -493,20 +471,16 @@ def configure_handler(self, config): factory = c else: klass = self.resolve(config.pop('class')) - #Special case for handler which refers to another handler - if issubclass(klass, logging.handlers.MemoryHandler) and\ - 'target' in config: + # Special case for handler which refers to another handler + if issubclass(klass, logging.handlers.MemoryHandler) and 'target' in config: try: config['target'] = self.config['handlers'][config['target']] except StandardError: e = sys.exc_info()[1] - raise ValueError('Unable to set target handler ' - '%r: %s' % (config['target'], e)) - elif issubclass(klass, logging.handlers.SMTPHandler) and\ - 'mailhost' in config: + raise ValueError('Unable to set target handler ' '%r: %s' % (config['target'], e)) + elif issubclass(klass, logging.handlers.SMTPHandler) and 'mailhost' in config: config['mailhost'] = self.as_tuple(config['mailhost']) - elif issubclass(klass, logging.handlers.SysLogHandler) and\ - 'address' in config: + elif issubclass(klass, logging.handlers.SysLogHandler) and 'address' in config: config['address'] = self.as_tuple(config['address']) factory = klass kwargs = dict([(k, config[k]) for k in config if valid_ident(k)]) @@ -516,10 +490,8 @@ def configure_handler(self, config): te = sys.exc_info()[1] if "'stream'" not in str(te): raise - #The argument name changed from strm to stream - #Retry with old name. - #This is so that code can be used with older Python versions - #(e.g. by Django) + # The argument name changed from strm to stream, so we retry with the old name. This is so that code can be + # used with older Python versions (e.g. by Django) kwargs['strm'] = kwargs.pop('stream') result = factory(**kwargs) if formatter: @@ -547,7 +519,7 @@ def common_logger_config(self, logger, config, incremental=False): if level is not None: logger.setLevel(_checkLevel(level)) if not incremental: - #Remove any existing handlers + # Remove any existing handlers for h in logger.handlers[:]: logger.removeHandler(h) handlers = config.get('handlers', None) @@ -570,8 +542,10 @@ def configure_root(self, config, incremental=False): root = logging.getLogger() self.common_logger_config(root, config, incremental) + dictConfigClass = DictConfigurator + def dictConfig(config): """Configure logging using a dictionary.""" dictConfigClass(config).configure() diff --git a/splunk_eventgen/lib/logutils_src/logutils/http.py b/splunk_eventgen/lib/logutils_src/logutils/http.py index d1fe99d3..2d59dc88 100644 --- a/splunk_eventgen/lib/logutils_src/logutils/http.py +++ b/splunk_eventgen/lib/logutils_src/logutils/http.py @@ -3,6 +3,7 @@ # import logging + class HTTPHandler(logging.Handler): """ A class which sends records to a Web server, using either GET or @@ -18,6 +19,7 @@ class HTTPHandler(logging.Handler): to avoid sending usernames and passwords in cleartext over the wire. """ + def __init__(self, host, url, method="GET", secure=False, credentials=None): """ Initialize an instance. @@ -51,7 +53,8 @@ def emit(self, record): :param record: The record to be emitted. """ try: - import http.client, urllib.parse + import http.client + import urllib.parse host = self.host if self.secure: h = http.client.HTTPSConnection(host) @@ -73,8 +76,7 @@ def emit(self, record): host = host[:i] h.putheader("Host", host) if self.method == "POST": - h.putheader("Content-type", - "application/x-www-form-urlencoded") + h.putheader("Content-type", "application/x-www-form-urlencoded") h.putheader("Content-length", str(len(data))) if self.credentials: import base64 @@ -82,7 +84,7 @@ def emit(self, record): s = 'Basic ' + base64.b64encode(s).strip() h.putheader('Authorization', s) h.endheaders(data if self.method == "POST" else None) - h.getresponse() #can't do anything with the result + h.getresponse() # can't do anything with the result except (KeyboardInterrupt, SystemExit): raise except: diff --git a/splunk_eventgen/lib/logutils_src/logutils/queue.py b/splunk_eventgen/lib/logutils_src/logutils/queue.py index fea91d8d..0a7d22a2 100644 --- a/splunk_eventgen/lib/logutils_src/logutils/queue.py +++ b/splunk_eventgen/lib/logutils_src/logutils/queue.py @@ -20,11 +20,13 @@ version here is for use with earlier Python versions. """ import logging +import threading + try: import Queue as queue except ImportError: import queue -import threading + class QueueHandler(logging.Handler): """ @@ -97,6 +99,7 @@ def emit(self, record): except: self.handleError(record) + class QueueListener(object): """ This class implements an internal threaded listener which watches for @@ -144,7 +147,7 @@ def start(self): t.setDaemon(True) t.start() - def prepare(self , record): + def prepare(self, record): """ Prepare a record for handling. diff --git a/splunk_eventgen/lib/logutils_src/logutils/redis.py b/splunk_eventgen/lib/logutils_src/logutils/redis.py index a8ead302..46641bf2 100644 --- a/splunk_eventgen/lib/logutils_src/logutils/redis.py +++ b/splunk_eventgen/lib/logutils_src/logutils/redis.py @@ -6,11 +6,13 @@ """ from logutils.queue import QueueHandler, QueueListener + try: import cPickle as pickle except ImportError: import pickle + class RedisQueueHandler(QueueHandler): """ A QueueHandler implementation which pushes pickled @@ -23,6 +25,7 @@ class RedisQueueHandler(QueueHandler): :param limit: If specified, the queue is restricted to have only this many elements. """ + def __init__(self, key='python.logging', redis=None, limit=0): if redis is None: from redis import Redis @@ -38,6 +41,7 @@ def enqueue(self, record): if self.limit: self.queue.ltrim(self.key, -self.limit, -1) + class RedisQueueListener(QueueListener): """ A QueueListener implementation which fetches pickled @@ -48,6 +52,7 @@ class RedisQueueListener(QueueListener): :param redis: If specified, this instance is used to communicate with a Redis instance. """ + def __init__(self, *handlers, **kwargs): redis = kwargs.get('redis') if redis is None: diff --git a/splunk_eventgen/lib/logutils_src/logutils/testing.py b/splunk_eventgen/lib/logutils_src/logutils/testing.py index 3c612179..bb8ac3df 100644 --- a/splunk_eventgen/lib/logutils_src/logutils/testing.py +++ b/splunk_eventgen/lib/logutils_src/logutils/testing.py @@ -1,9 +1,9 @@ # # Copyright (C) 2010-2017 Vinay Sajip. See LICENSE.txt for details. # -import logging from logging.handlers import BufferingHandler + class TestHandler(BufferingHandler): """ This handler collects records in a buffer for later inspection by @@ -12,6 +12,7 @@ class TestHandler(BufferingHandler): :param matcher: The :class:`~logutils.testing.Matcher` instance to use for matching. """ + def __init__(self, matcher): # BufferingHandler takes a "capacity" argument # so as to know when to flush. As we're overriding @@ -64,8 +65,8 @@ def matches(self, **kwargs): if self.matcher.matches(d, **kwargs): result = True break - #if not result: - # print('*** matcher failed completely on %d records' % len(self.buffer)) + # if not result: + # print('*** matcher failed completely on %d records' % len(self.buffer)) return result def matchall(self, kwarglist): @@ -96,6 +97,7 @@ def count(self): """ return len(self.buffer) + class Matcher(object): """ This utility class matches a stored dictionary of @@ -129,7 +131,7 @@ def matches(self, d, **kwargs): v = kwargs[k] dv = d.get(k) if not self.match_value(k, dv, v): - #print('*** matcher failed: %s, %r, %r' % (k, dv, v)) + # print('*** matcher failed: %s, %r, %r' % (k, dv, v)) result = False break return result @@ -150,6 +152,6 @@ def match_value(self, k, dv, v): result = (v == dv) else: result = dv.find(v) >= 0 - #if not result: + # if not result: # print('*** matcher failed on %s: %r vs. %r' % (k, dv, v)) return result diff --git a/splunk_eventgen/lib/logutils_src/logutils_src_setup.py b/splunk_eventgen/lib/logutils_src/logutils_src_setup.py index f0891d65..8eb90944 100644 --- a/splunk_eventgen/lib/logutils_src/logutils_src_setup.py +++ b/splunk_eventgen/lib/logutils_src/logutils_src_setup.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- import distutils.core -import logutils -from os.path import join, dirname, abspath import re +from os.path import dirname, join + +import logutils def description(): @@ -16,6 +17,7 @@ def description(): avail, = re.findall(regexp, readme, re.DOTALL) return reqts + avail + class TestCommand(distutils.core.Command): user_options = [] @@ -37,6 +39,7 @@ def initialize_options(self): def finalize_options(self): pass + distutils.core.setup( name='logutils', version=logutils.__version__, @@ -44,7 +47,7 @@ def finalize_options(self): author_email='vinay_sajip@red-dove.com', url='http://code.google.com/p/logutils/', description='Logging utilities', - long_description = description(), + long_description=description(), license='Copyright (C) 2010-2017 by Vinay Sajip. All Rights Reserved. See LICENSE.txt for license.', classifiers=[ 'Development Status :: 5 - Production/Stable', @@ -55,11 +58,8 @@ def finalize_options(self): 'Programming Language :: Python', "Programming Language :: Python :: 2", "Programming Language :: Python :: 3", - 'Topic :: Software Development', - ], + 'Topic :: Software Development', ], packages=['logutils'], cmdclass={ - 'test': TestCommand, - }, - + 'test': TestCommand, }, ) diff --git a/splunk_eventgen/lib/logutils_src/tests/logutil_tests.py b/splunk_eventgen/lib/logutils_src/tests/logutil_tests.py deleted file mode 100644 index e86d1062..00000000 --- a/splunk_eventgen/lib/logutils_src/tests/logutil_tests.py +++ /dev/null @@ -1,22 +0,0 @@ -# -# Copyright (C) 2008-2017 Vinay Sajip. See LICENSE.txt for details. -# -import sys -from test_testing import LoggingTest -from test_dictconfig import ConfigDictTest -from test_queue import QueueTest -from test_formatter import FormatterTest -from test_messages import MessageTest -from test_colorize import ColorizeTest -try: - from test_redis import RedisQueueTest -except ImportError: - pass - -# The adapter won't work in < 2.5 because the "extra" parameter used by it -# only appeared in 2.5 :-( -if sys.version_info[:2] >= (2, 5): - from test_adapter import AdapterTest -else: - print("LoggerAdapter won't work in Python < 2.5, so its tests are being " - "skipped.") diff --git a/splunk_eventgen/lib/logutils_src/tests/mytest.py b/splunk_eventgen/lib/logutils_src/tests/mytest.py index a5f40d32..ac9cbcc2 100644 --- a/splunk_eventgen/lib/logutils_src/tests/mytest.py +++ b/splunk_eventgen/lib/logutils_src/tests/mytest.py @@ -1,6 +1,7 @@ from __future__ import absolute_import -from logutils.testing import TestHandler, Matcher +from logutils.testing import Matcher, TestHandler + class MyTestHandler(TestHandler): def __init__(self): diff --git a/splunk_eventgen/lib/logutils_src/tests/test_adapter.py b/splunk_eventgen/lib/logutils_src/tests/test_adapter.py index d29bd106..a827f95d 100644 --- a/splunk_eventgen/lib/logutils_src/tests/test_adapter.py +++ b/splunk_eventgen/lib/logutils_src/tests/test_adapter.py @@ -2,23 +2,25 @@ # Copyright (C) 2008-2017 Vinay Sajip. See LICENSE.txt for details. # import logging -from logutils.adapter import LoggerAdapter -from logutils.testing import TestHandler, Matcher import unittest +from logutils.adapter import LoggerAdapter +from logutils.testing import Matcher, TestHandler + + class AdapterTest(unittest.TestCase): def setUp(self): self.handler = h = TestHandler(Matcher()) - self.logger = l = logging.getLogger() - l.addHandler(h) - self.adapter = LoggerAdapter(l, {}) + self.logger = temp_logger = logging.getLogger() + temp_logger.addHandler(h) + self.adapter = LoggerAdapter(temp_logger, {}) def tearDown(self): self.logger.removeHandler(self.handler) self.handler.close() def test_simple(self): - "Simple test of logging test harness." + """Simple test of logging test harness.""" # Just as a demo, let's log some messages. # Only one should show up in the log. self.adapter.debug("This won't show up.") @@ -30,20 +32,20 @@ def test_simple(self): self.assertFalse(h.matches(levelno=logging.INFO)) def test_partial(self): - "Test of partial matching in logging test harness." + """Test of partial matching in logging test harness.""" # Just as a demo, let's log some messages. # Only one should show up in the log. self.adapter.debug("This won't show up.") self.adapter.info("Neither will this.") self.adapter.warning("But this will.") h = self.handler - self.assertTrue(h.matches(msg="ut th")) # from "But this will" - self.assertTrue(h.matches(message="ut th")) # from "But this will" + self.assertTrue(h.matches(msg="ut th")) # from "But this will" + self.assertTrue(h.matches(message="ut th")) # from "But this will" self.assertFalse(h.matches(message="either")) self.assertFalse(h.matches(message="won't")) def test_multiple(self): - "Test of matching multiple values in logging test harness." + """Test of matching multiple values in logging test harness.""" # Just as a demo, let's log some messages. # Only one should show up in the log. self.adapter.debug("This won't show up.") @@ -51,19 +53,18 @@ def test_multiple(self): self.adapter.warning("But this will.") self.adapter.error("And so will this.") h = self.handler - self.assertTrue(h.matches(levelno=logging.WARNING, - message='ut th')) - self.assertTrue(h.matches(levelno=logging.ERROR, - message='nd so w')) + self.assertTrue(h.matches(levelno=logging.WARNING, message='ut th')) + self.assertTrue(h.matches(levelno=logging.ERROR, message='nd so w')) self.assertFalse(h.matches(levelno=logging.INFO)) def test_hashandlers(self): - "Test of hasHandlers() functionality." + """Test of hasHandlers() functionality.""" self.assertTrue(self.adapter.hasHandlers()) self.logger.removeHandler(self.handler) self.assertFalse(self.adapter.hasHandlers()) self.logger.addHandler(self.handler) self.assertTrue(self.adapter.hasHandlers()) + if __name__ == '__main__': unittest.main() diff --git a/splunk_eventgen/lib/logutils_src/tests/test_colorize.py b/splunk_eventgen/lib/logutils_src/tests/test_colorize.py index 022b6318..18d1b263 100644 --- a/splunk_eventgen/lib/logutils_src/tests/test_colorize.py +++ b/splunk_eventgen/lib/logutils_src/tests/test_colorize.py @@ -2,18 +2,18 @@ # Copyright (C) 2012-2017 Vinay Sajip. See LICENSE.txt for details. # import logging -import logutils.colorize -import os import sys import unittest +import logutils.colorize + if sys.version_info[0] < 3: u = lambda o: unicode(o, 'unicode_escape') else: u = lambda o: o -class ColorizeTest(unittest.TestCase): +class ColorizeTest(unittest.TestCase): def test_colorize(self): logger = logging.getLogger() handler = logutils.colorize.ColorizingStreamHandler() diff --git a/splunk_eventgen/lib/logutils_src/tests/test_dictconfig.py b/splunk_eventgen/lib/logutils_src/tests/test_dictconfig.py index 3aee9841..950bcc6c 100644 --- a/splunk_eventgen/lib/logutils_src/tests/test_dictconfig.py +++ b/splunk_eventgen/lib/logutils_src/tests/test_dictconfig.py @@ -2,41 +2,47 @@ # Copyright 2009-2017 by Vinay Sajip. See LICENSE.txt for details. # import logging +import unittest + from logutils.adapter import LoggerAdapter from logutils.dictconfig import dictConfig, named_handlers_supported -from logutils.testing import TestHandler, Matcher -import sys -import unittest +from logutils.testing import Matcher, TestHandler try: StandardError except NameError: StandardError = Exception + class ExceptionFormatter(logging.Formatter): """A special exception formatter.""" + def formatException(self, ei): return "Got a [%s]" % ei[0].__name__ + def formatFunc(format, datefmt=None): return logging.Formatter(format, datefmt) + def testHandler(): return TestHandler(Matcher()) + def handlerFunc(): return logging.StreamHandler() + class CustomHandler(logging.StreamHandler): pass -class ConfigDictTest(unittest.TestCase): +class ConfigDictTest(unittest.TestCase): """Reading logging config from a dictionary.""" def setUp(self): - self.logger = l = logging.getLogger() - self.adapter = LoggerAdapter(l, {}) + self.logger = temp_logger = logging.getLogger() + self.adapter = LoggerAdapter(temp_logger, {}) logger_dict = logging.getLogger().manager.loggerDict logging._acquireLock() @@ -55,7 +61,6 @@ def setUp(self): self.root_logger = logging.getLogger("") self.original_logging_level = self.root_logger.getEffectiveLevel() - def tearDown(self): self.root_logger.setLevel(self.original_logging_level) logging._acquireLock() @@ -89,429 +94,287 @@ def next_message(self): config0 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - '()': testHandler, - 'formatter': 'form1', - } - }, - 'root' : { - 'level' : 'WARNING', - 'handlers' : ['hand1'], - }, - } + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': {'hand1': { + '()': testHandler, + 'formatter': 'form1', }}, + 'root': { + 'level': 'WARNING', + 'handlers': ['hand1'], }, } # config1 adds a little to the standard configuration. config1 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - '()': testHandler, - 'formatter': 'form1', - } - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], - }, - }, - 'root' : { - 'level' : 'WARNING', - }, - } + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': {'hand1': { + '()': testHandler, + 'formatter': 'form1', }}, + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, + 'root': { + 'level': 'WARNING', }, } # config2 has a subtle configuration error that should be reported config2 = { 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdbout', - }, - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], - }, - }, - 'root' : { - 'level' : 'WARNING', - }, - } - - #As config1 but with a misspelt level on a handler + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdbout', }, }, + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, + 'root': { + 'level': 'WARNING', }, } + + # As config1 but with a misspelt level on a handler config2a = { 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NTOSET', - 'stream' : 'ext://sys.stdout', - }, - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], - }, - }, - 'root' : { - 'level' : 'WARNING', - }, - } - - - #As config1 but with a misspelt level on a logger + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NTOSET', + 'stream': 'ext://sys.stdout', }, }, + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, + 'root': { + 'level': 'WARNING', }, } + + # As config1 but with a misspelt level on a logger config2b = { 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', - }, - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], - }, - }, - 'root' : { - 'level' : 'WRANING', - }, - } + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, + 'root': { + 'level': 'WRANING', }, } # config3 has a less subtle configuration error config3 = { 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'misspelled_name', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', - }, - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], - }, - }, - 'root' : { - 'level' : 'WARNING', - }, - } + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'misspelled_name', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, + 'root': { + 'level': 'WARNING', }, } # config4 specifies a custom formatter class to be loaded config4 = { 'version': 1, 'formatters': { - 'form1' : { - '()' : __name__ + '.ExceptionFormatter', - 'format' : '%(levelname)s:%(name)s:%(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - '()': testHandler, - 'formatter': 'form1', - } - }, - 'root' : { - 'level' : 'NOTSET', - 'handlers' : ['hand1'], - }, - } + 'form1': { + '()': __name__ + '.ExceptionFormatter', + 'format': '%(levelname)s:%(name)s:%(message)s', }, }, + 'handlers': {'hand1': { + '()': testHandler, + 'formatter': 'form1', }}, + 'root': { + 'level': 'NOTSET', + 'handlers': ['hand1'], }, } # As config4 but using an actual callable rather than a string config4a = { 'version': 1, 'formatters': { - 'form1' : { - '()' : ExceptionFormatter, - 'format' : '%(levelname)s:%(name)s:%(message)s', - }, - 'form2' : { - '()' : __name__ + '.formatFunc', - 'format' : '%(levelname)s:%(name)s:%(message)s', - }, - 'form3' : { - '()' : formatFunc, - 'format' : '%(levelname)s:%(name)s:%(message)s', - }, - }, - 'handlers' : { - 'hand1' : { + 'form1': { + '()': ExceptionFormatter, + 'format': '%(levelname)s:%(name)s:%(message)s', }, + 'form2': { + '()': __name__ + '.formatFunc', + 'format': '%(levelname)s:%(name)s:%(message)s', }, + 'form3': { + '()': formatFunc, + 'format': '%(levelname)s:%(name)s:%(message)s', }, }, + 'handlers': { + 'hand1': { '()': testHandler, - 'formatter': 'form1', - }, - 'hand2' : { - '()' : handlerFunc, - }, - }, - 'root' : { - 'level' : 'NOTSET', - 'handlers' : ['hand1'], - }, - } + 'formatter': 'form1', }, + 'hand2': { + '()': handlerFunc, }, }, + 'root': { + 'level': 'NOTSET', + 'handlers': ['hand1'], }, } # config5 specifies a custom handler class to be loaded config5 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - '()': testHandler, - 'formatter': 'form1', - } - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], - }, - }, - 'root' : { - 'level' : 'WARNING', - }, - } + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': {'hand1': { + '()': testHandler, + 'formatter': 'form1', }}, + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, + 'root': { + 'level': 'WARNING', }, } # config6 specifies a custom handler class to be loaded # but has bad arguments config6 = { 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - 'class' : __name__ + '.CustomHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', - '9' : 'invalid parameter name', - }, - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], - }, - }, - 'root' : { - 'level' : 'WARNING', - }, - } - - #config 7 does not define compiler.parser but defines compiler.lexer - #so compiler.parser should be disabled after applying it + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': { + 'hand1': { + 'class': __name__ + '.CustomHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', + '9': 'invalid parameter name', }, }, + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, + 'root': { + 'level': 'WARNING', }, } + + # config 7 does not define compiler.parser but defines compiler.lexer + # so compiler.parser should be disabled after applying it config7 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - '()': testHandler, - 'formatter': 'form1', - } - }, - 'loggers' : { - 'compiler.lexer' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], - }, - }, - 'root' : { - 'level' : 'WARNING', - }, - } + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': {'hand1': { + '()': testHandler, + 'formatter': 'form1', }}, + 'loggers': { + 'compiler.lexer': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, + 'root': { + 'level': 'WARNING', }, } config8 = { 'version': 1, - 'disable_existing_loggers' : False, + 'disable_existing_loggers': False, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - '()': testHandler, - 'formatter': 'form1', - } - }, - 'loggers' : { - 'compiler' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], - }, - 'compiler.lexer' : { - }, - }, - 'root' : { - 'level' : 'WARNING', - }, - } + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': {'hand1': { + '()': testHandler, + 'formatter': 'form1', }}, + 'loggers': { + 'compiler': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, + 'compiler.lexer': {}, }, + 'root': { + 'level': 'WARNING', }, } config9 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'handlers' : { - 'hand1' : { - '()': testHandler, - 'formatter': 'form1', - } - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'WARNING', - 'handlers' : ['hand1'], - }, - }, - 'root' : { - 'level' : 'NOTSET', - }, - } + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'handlers': {'hand1': { + '()': testHandler, + 'formatter': 'form1', }}, + 'loggers': { + 'compiler.parser': { + 'level': 'WARNING', + 'handlers': ['hand1'], }, }, + 'root': { + 'level': 'NOTSET', }, } config9a = { 'version': 1, - 'incremental' : True, - 'handlers' : { - 'hand1' : { - 'level' : 'WARNING', - }, - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'INFO', - }, - }, - } + 'incremental': True, + 'handlers': { + 'hand1': { + 'level': 'WARNING', }, }, + 'loggers': { + 'compiler.parser': { + 'level': 'INFO', }, }, } config9b = { 'version': 1, - 'incremental' : True, - 'handlers' : { - 'hand1' : { - 'level' : 'INFO', - }, - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'INFO', - }, - }, - } - - #As config1 but with a filter added + 'incremental': True, + 'handlers': { + 'hand1': { + 'level': 'INFO', }, }, + 'loggers': { + 'compiler.parser': { + 'level': 'INFO', }, }, } + + # As config1 but with a filter added config10 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'filters' : { - 'filt1' : { - 'name' : 'compiler.parser', - }, - }, - 'handlers' : { - 'hand1' : { - '()': testHandler, - 'formatter': 'form1', - 'filters' : ['filt1'], - } - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'filters' : ['filt1'], - }, - }, - 'root' : { - 'level' : 'WARNING', - 'handlers' : ['hand1'], - }, - } + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'filters': { + 'filt1': { + 'name': 'compiler.parser', }, }, + 'handlers': {'hand1': { + '()': testHandler, + 'formatter': 'form1', + 'filters': ['filt1'], }}, + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'filters': ['filt1'], }, }, + 'root': { + 'level': 'WARNING', + 'handlers': ['hand1'], }, } # As config10, but declaring a handler in a module using # absolute imports config11 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', - }, - }, - 'filters' : { - 'filt1' : { - 'name' : 'compiler.parser', - }, - }, - 'handlers' : { - 'hand1' : { - '()': 'mytest.MyTestHandler', - 'formatter': 'form1', - 'filters' : ['filt1'], - } - }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'filters' : ['filt1'], - }, - }, - 'root' : { - 'level' : 'WARNING', - 'handlers' : ['hand1'], - }, - } + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, + 'filters': { + 'filt1': { + 'name': 'compiler.parser', }, }, + 'handlers': {'hand1': { + '()': 'mytest.MyTestHandler', + 'formatter': 'form1', + 'filters': ['filt1'], }}, + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'filters': ['filt1'], }, }, + 'root': { + 'level': 'WARNING', + 'handlers': ['hand1'], }, } def apply_config(self, conf): dictConfig(conf) @@ -526,9 +389,7 @@ def test_config0_ok(self): logger.error(self.next_message()) h = logger.handlers[0] self.assertEqual(1, h.count) - self.assertTrue(h.matchall([ - dict(levelname='ERROR', message='2') - ])) + self.assertTrue(h.matchall([dict(levelname='ERROR', message='2')])) def test_config1_ok(self, config=config1): # A config defining a sub-parser as well. @@ -539,9 +400,8 @@ def test_config1_ok(self, config=config1): logger.error(self.next_message()) h = logger.handlers[0] self.assertTrue(h.matchall([ - dict(levelname='INFO', message='1'), - dict(levelname='ERROR', message='2'), - ])) + dict(levelname='INFO', message='1'), + dict(levelname='ERROR', message='2'), ])) def test_config2_failure(self): # A simple config which overrides the default settings. @@ -568,8 +428,7 @@ def test_config4_ok(self): raise RuntimeError() except RuntimeError: logging.exception("just testing") - self.assertEquals(h.formatted[0], - "ERROR:root:just testing\nGot a [RuntimeError]") + self.assertEquals(h.formatted[0], "ERROR:root:just testing\nGot a [RuntimeError]") def test_config4a_ok(self): # A config specifying a custom formatter class. @@ -580,8 +439,7 @@ def test_config4a_ok(self): raise RuntimeError() except RuntimeError: logging.exception("just testing") - self.assertEquals(h.formatted[0], - "ERROR:root:just testing\nGot a [RuntimeError]") + self.assertEquals(h.formatted[0], "ERROR:root:just testing\nGot a [RuntimeError]") def test_config5_ok(self): self.test_config1_ok(config=self.config5) @@ -597,9 +455,8 @@ def test_config7_ok(self): logger.error(self.next_message()) h = logger.handlers[0] self.assertTrue(h.matchall([ - dict(levelname='INFO', message='1'), - dict(levelname='ERROR', message='2'), - ])) + dict(levelname='INFO', message='1'), + dict(levelname='ERROR', message='2'), ])) self.apply_config(self.config7) logger = logging.getLogger("compiler.parser") self.assertTrue(logger.disabled) @@ -609,11 +466,10 @@ def test_config7_ok(self): logger.info(self.next_message()) logger.error(self.next_message()) self.assertTrue(h.matchall([ - dict(levelname='INFO', message='3'), - dict(levelname='ERROR', message='4'), - ])) + dict(levelname='INFO', message='3'), + dict(levelname='ERROR', message='4'), ])) - #Same as test_config_7_ok but don't disable old loggers. + # Same as test_config_7_ok but don't disable old loggers. def test_config_8_ok(self): self.apply_config(self.config1) logger = logging.getLogger("compiler.parser") @@ -622,9 +478,8 @@ def test_config_8_ok(self): logger.error(self.next_message()) h = logger.handlers[0] self.assertTrue(h.matchall([ - dict(levelname='INFO', message='1'), - dict(levelname='ERROR', message='2'), - ])) + dict(levelname='INFO', message='1'), + dict(levelname='ERROR', message='2'), ])) self.apply_config(self.config8) logger = logging.getLogger("compiler.parser") self.assertFalse(logger.disabled) @@ -637,22 +492,22 @@ def test_config_8_ok(self): logger.info(self.next_message()) logger.error(self.next_message()) h = toplogger.handlers[0] - self.assertTrue(h.matchall([ - dict(levelname='INFO', message='3'), - dict(levelname='ERROR', message='4'), - dict(levelname='INFO', message='5'), - dict(levelname='ERROR', message='6'), - ])) + self.assertTrue( + h.matchall([ + dict(levelname='INFO', message='3'), + dict(levelname='ERROR', message='4'), + dict(levelname='INFO', message='5'), + dict(levelname='ERROR', message='6'), ])) def test_config_9_ok(self): self.apply_config(self.config9) logger = logging.getLogger("compiler.parser") - #Nothing will be output since both handler and logger are set to WARNING + # Nothing will be output since both handler and logger are set to WARNING logger.info(self.next_message()) h = logger.handlers[0] self.assertEqual(0, h.count) self.apply_config(self.config9a) - #Nothing will be output since both handler is still set to WARNING + # Nothing will be output since both handler is still set to WARNING logger.info(self.next_message()) h = logger.handlers[0] nhs = named_handlers_supported() @@ -661,13 +516,12 @@ def test_config_9_ok(self): else: self.assertEqual(1, h.count) self.apply_config(self.config9b) - #Message should now be output + # Message should now be output logger.info(self.next_message()) if nhs: h = logger.handlers[0] self.assertTrue(h.matchall([ - dict(levelname='INFO', message='3'), - ])) + dict(levelname='INFO', message='3'), ])) else: self.assertEqual(2, h.count) @@ -676,19 +530,18 @@ def test_config_10_ok(self): logger = logging.getLogger("compiler.parser") logger.warning(self.next_message()) logger = logging.getLogger('compiler') - #Not output, because filtered + # Not output, because filtered logger.warning(self.next_message()) logger = logging.getLogger('compiler.lexer') - #Not output, because filtered + # Not output, because filtered logger.warning(self.next_message()) logger = logging.getLogger("compiler.parser.codegen") - #Output, as not filtered + # Output, as not filtered logger.error(self.next_message()) h = logging.getLogger().handlers[0] self.assertTrue(h.matchall([ - dict(levelname='WARNING', message='1'), - dict(levelname='ERROR', message='4'), - ])) + dict(levelname='WARNING', message='1'), + dict(levelname='ERROR', message='4'), ])) def test_config_11_ok(self): self.apply_config(self.config11) diff --git a/splunk_eventgen/lib/logutils_src/tests/test_formatter.py b/splunk_eventgen/lib/logutils_src/tests/test_formatter.py index 0a069c78..011ba234 100644 --- a/splunk_eventgen/lib/logutils_src/tests/test_formatter.py +++ b/splunk_eventgen/lib/logutils_src/tests/test_formatter.py @@ -2,11 +2,13 @@ # Copyright (C) 2009-2017 Vinay Sajip. See LICENSE.txt for details. # import logging -import logutils import os import sys import unittest +import logutils + + class FormatterTest(unittest.TestCase): def setUp(self): self.common = { @@ -17,10 +19,8 @@ def setUp(self): 'exc_info': None, 'func': None, 'msg': 'Message with %d %s', - 'args': (2, 'placeholders'), - } - self.variants = { - } + 'args': (2, 'placeholders'), } + self.variants = {} def get_record(self, name=None): result = dict(self.common) @@ -42,6 +42,7 @@ def test_percent(self): self.assertFalse(f.usesTime()) if sys.version_info[:2] >= (2, 6): + def test_braces(self): "Test {}-formatting" r = self.get_record() diff --git a/splunk_eventgen/lib/logutils_src/tests/test_messages.py b/splunk_eventgen/lib/logutils_src/tests/test_messages.py index 17f80bbd..0a221105 100644 --- a/splunk_eventgen/lib/logutils_src/tests/test_messages.py +++ b/splunk_eventgen/lib/logutils_src/tests/test_messages.py @@ -1,9 +1,12 @@ -import logutils import sys import unittest +import logutils + + class MessageTest(unittest.TestCase): if sys.version_info[:2] >= (2, 6): + def test_braces(self): "Test whether brace-formatting works." __ = logutils.BraceMessage @@ -19,8 +22,7 @@ class Dummy: dummy = Dummy() dummy.x, dummy.y = 0.0, 1.0 - m = __('Message with coordinates: ({point.x:.2f}, {point.y:.2f})', - point=dummy) + m = __('Message with coordinates: ({point.x:.2f}, {point.y:.2f})', point=dummy) self.assertEqual(str(m), 'Message with coordinates: (0.00, 1.00)') def test_dollars(self): @@ -29,5 +31,4 @@ def test_dollars(self): m = __('Message with $num ${what}', num=2, what='placeholders') self.assertEqual(str(m), 'Message with 2 placeholders') ignored = object() - self.assertRaises(TypeError, __, 'Message with $num ${what}', - ignored, num=2, what='placeholders') + self.assertRaises(TypeError, __, 'Message with $num ${what}', ignored, num=2, what='placeholders') diff --git a/splunk_eventgen/lib/logutils_src/tests/test_queue.py b/splunk_eventgen/lib/logutils_src/tests/test_queue.py index 34152e37..f85074c6 100644 --- a/splunk_eventgen/lib/logutils_src/tests/test_queue.py +++ b/splunk_eventgen/lib/logutils_src/tests/test_queue.py @@ -2,19 +2,21 @@ # Copyright (C) 2010-2017 Vinay Sajip. See LICENSE.txt for details. # import logging -from logutils.testing import TestHandler, Matcher -from logutils.queue import QueueHandler, QueueListener, queue import unittest +from logutils.queue import QueueHandler, QueueListener, queue +from logutils.testing import Matcher, TestHandler + + class QueueTest(unittest.TestCase): def setUp(self): self.handler = h = TestHandler(Matcher()) - self.logger = l = logging.getLogger() + self.logger = temp_logger = logging.getLogger() self.queue = q = queue.Queue(-1) self.qh = qh = QueueHandler(q) self.ql = ql = QueueListener(q, h) ql.start() - l.addHandler(qh) + temp_logger.addHandler(qh) def tearDown(self): self.logger.removeHandler(self.qh) @@ -28,9 +30,8 @@ def test_simple(self): self.logger.debug("This won't show up.") self.logger.info("Neither will this.") self.logger.warning("But this will.") - self.ql.stop() #ensure all records have come through. + self.ql.stop() # ensure all records have come through. h = self.handler - #import pdb; pdb.set_trace() self.assertTrue(h.matches(levelno=logging.WARNING)) self.assertFalse(h.matches(levelno=logging.DEBUG)) self.assertFalse(h.matches(levelno=logging.INFO)) @@ -42,10 +43,10 @@ def test_partial(self): self.logger.debug("This won't show up.") self.logger.info("Neither will this.") self.logger.warning("But this will.") - self.ql.stop() #ensure all records have come through. + self.ql.stop() # ensure all records have come through. h = self.handler - self.assertTrue(h.matches(msg="ut th")) # from "But this will" - self.assertTrue(h.matches(message="ut th")) # from "But this will" + self.assertTrue(h.matches(msg="ut th")) # from "But this will" + self.assertTrue(h.matches(message="ut th")) # from "But this will" self.assertFalse(h.matches(message="either")) self.assertFalse(h.matches(message="won't")) @@ -57,13 +58,12 @@ def test_multiple(self): self.logger.info("Neither will this.") self.logger.warning("But this will.") self.logger.error("And so will this.") - self.ql.stop() #ensure all records have come through. + self.ql.stop() # ensure all records have come through. h = self.handler - self.assertTrue(h.matches(levelno=logging.WARNING, - message='ut thi')) - self.assertTrue(h.matches(levelno=logging.ERROR, - message='nd so wi')) + self.assertTrue(h.matches(levelno=logging.WARNING, message='ut thi')) + self.assertTrue(h.matches(levelno=logging.ERROR, message='nd so wi')) self.assertFalse(h.matches(levelno=logging.INFO)) + if __name__ == '__main__': unittest.main() diff --git a/splunk_eventgen/lib/logutils_src/tests/test_redis.py b/splunk_eventgen/lib/logutils_src/tests/test_redis.py index 858192cd..e53bdb5d 100644 --- a/splunk_eventgen/lib/logutils_src/tests/test_redis.py +++ b/splunk_eventgen/lib/logutils_src/tests/test_redis.py @@ -2,14 +2,17 @@ # Copyright (C) 2011-2017 Vinay Sajip. See LICENSE.txt for details. # import logging -from logutils.testing import TestHandler, Matcher -from logutils.redis import RedisQueueHandler, RedisQueueListener -from redis import Redis import socket import subprocess import time import unittest +from logutils.redis import RedisQueueHandler, RedisQueueListener +from logutils.testing import Matcher, TestHandler + +from redis import Redis + + class QueueListener(RedisQueueListener): def dequeue(self, block): record = RedisQueueListener.dequeue(self, block) @@ -17,19 +20,18 @@ def dequeue(self, block): record = logging.makeLogRecord(record) return record + class RedisQueueTest(unittest.TestCase): def setUp(self): self.handler = h = TestHandler(Matcher()) - self.logger = l = logging.getLogger() - self.server = subprocess.Popen(['redis-server'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + self.logger = temp_logger = logging.getLogger() + self.server = subprocess.Popen(['redis-server'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) self.wait_for_server() self.queue = q = Redis() self.qh = qh = RedisQueueHandler(redis=q) self.ql = ql = QueueListener(h, redis=q) ql.start() - l.addHandler(qh) + temp_logger.addHandler(qh) def tearDown(self): self.logger.removeHandler(self.qh) @@ -38,7 +40,7 @@ def tearDown(self): self.server.terminate() def wait_for_server(self): - maxtime = time.time() + 2 # 2 seconds to wait for server + maxtime = time.time() + 2 # 2 seconds to wait for server sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) while time.time() < maxtime: try: @@ -57,9 +59,8 @@ def test_simple(self): self.logger.debug("This won't show up.") self.logger.info("Neither will this.") self.logger.warning("But this will.") - self.ql.stop() #ensure all records have come through. + self.ql.stop() # ensure all records have come through. h = self.handler - #import pdb; pdb.set_trace() self.assertTrue(h.matches(levelno=logging.WARNING)) self.assertFalse(h.matches(levelno=logging.DEBUG)) self.assertFalse(h.matches(levelno=logging.INFO)) @@ -71,10 +72,10 @@ def test_partial(self): self.logger.debug("This won't show up.") self.logger.info("Neither will this.") self.logger.warning("But this will.") - self.ql.stop() #ensure all records have come through. + self.ql.stop() # ensure all records have come through. h = self.handler - self.assertTrue(h.matches(msg="ut th")) # from "But this will" - self.assertTrue(h.matches(message="ut th")) # from "But this will" + self.assertTrue(h.matches(msg="ut th")) # from "But this will" + self.assertTrue(h.matches(message="ut th")) # from "But this will" self.assertFalse(h.matches(message="either")) self.assertFalse(h.matches(message="won't")) @@ -86,13 +87,12 @@ def test_multiple(self): self.logger.info("Neither will this.") self.logger.warning("But this will.") self.logger.error("And so will this.") - self.ql.stop() #ensure all records have come through. + self.ql.stop() # ensure all records have come through. h = self.handler - self.assertTrue(h.matches(levelno=logging.WARNING, - message='ut thi')) - self.assertTrue(h.matches(levelno=logging.ERROR, - message='nd so wi')) + self.assertTrue(h.matches(levelno=logging.WARNING, message='ut thi')) + self.assertTrue(h.matches(levelno=logging.ERROR, message='nd so wi')) self.assertFalse(h.matches(levelno=logging.INFO)) + if __name__ == '__main__': unittest.main() diff --git a/splunk_eventgen/lib/logutils_src/tests/test_testing.py b/splunk_eventgen/lib/logutils_src/tests/test_testing.py index c0b7409a..ef61beb7 100644 --- a/splunk_eventgen/lib/logutils_src/tests/test_testing.py +++ b/splunk_eventgen/lib/logutils_src/tests/test_testing.py @@ -2,21 +2,23 @@ # Copyright (C) 2010-2017 Vinay Sajip. See LICENSE.txt for details. # import logging -from logutils.testing import TestHandler, Matcher import unittest +from logutils.testing import Matcher, TestHandler + + class LoggingTest(unittest.TestCase): def setUp(self): self.handler = h = TestHandler(Matcher()) - self.logger = l = logging.getLogger() - l.addHandler(h) + self.logger = temp_logger = logging.getLogger() + temp_logger.addHandler(h) def tearDown(self): self.logger.removeHandler(self.handler) self.handler.close() def test_simple(self): - "Simple test of logging test harness." + """Simple test of logging test harness.""" # Just as a demo, let's log some messages. # Only one should show up in the log. self.logger.debug("This won't show up.") @@ -28,20 +30,20 @@ def test_simple(self): self.assertFalse(h.matches(levelno=logging.INFO)) def test_partial(self): - "Test of partial matching in logging test harness." + """Test of partial matching in logging test harness.""" # Just as a demo, let's log some messages. # Only one should show up in the log. self.logger.debug("This won't show up.") self.logger.info("Neither will this.") self.logger.warning("But this will.") h = self.handler - self.assertTrue(h.matches(msg="ut th")) # from "But this will" - self.assertTrue(h.matches(message="ut th")) # from "But this will" + self.assertTrue(h.matches(msg="ut th")) # from "But this will" + self.assertTrue(h.matches(message="ut th")) # from "But this will" self.assertFalse(h.matches(message="either")) self.assertFalse(h.matches(message="won't")) def test_multiple(self): - "Test of matching multiple values in logging test harness." + """Test of matching multiple values in logging test harness.""" # Just as a demo, let's log some messages. # Only one should show up in the log. self.logger.debug("This won't show up.") @@ -49,11 +51,10 @@ def test_multiple(self): self.logger.warning("But this will.") self.logger.error("And so will this.") h = self.handler - self.assertTrue(h.matches(levelno=logging.WARNING, - message='ut thi')) - self.assertTrue(h.matches(levelno=logging.ERROR, - message='nd so wi')) + self.assertTrue(h.matches(levelno=logging.WARNING, message='ut thi')) + self.assertTrue(h.matches(levelno=logging.ERROR, message='nd so wi')) self.assertFalse(h.matches(levelno=logging.INFO)) + if __name__ == '__main__': unittest.main() diff --git a/splunk_eventgen/lib/outputcounter.py b/splunk_eventgen/lib/outputcounter.py index 37547f11..46d455e2 100644 --- a/splunk_eventgen/lib/outputcounter.py +++ b/splunk_eventgen/lib/outputcounter.py @@ -1,11 +1,13 @@ -import time import logging +import time + class OutputCounter(object): ''' This object is used as a global variable for outputer to collect how many events and how much size of raw events egx has generated, and use them to calculate a real-time throughput. ''' + def __init__(self): self.event_size_1_min = 0 self.event_count_1_min = 0 @@ -24,7 +26,8 @@ def update_throughput(self, timestamp): self.current_time = timestamp self.event_count_1_min = 0 self.event_size_1_min = 0 - self.logger.error("Current throughput is {} B/s, {} count/s".format(self.throughput_volume, self.throughput_count)) + self.logger.debug("Current throughput is {} B/s, {} count/s".format(self.throughput_volume, + self.throughput_count)) def collect(self, event_count, event_size): timestamp = time.time() diff --git a/splunk_eventgen/lib/outputplugin.py b/splunk_eventgen/lib/outputplugin.py index f1dee615..e3bb2fb3 100644 --- a/splunk_eventgen/lib/outputplugin.py +++ b/splunk_eventgen/lib/outputplugin.py @@ -1,8 +1,10 @@ from __future__ import division + import logging import logging.handlers from collections import deque + class OutputPlugin(object): name = 'OutputPlugin' @@ -12,14 +14,15 @@ def __init__(self, sample, output_counter=None): self._outputMode = sample.outputMode self.events = None self._setup_logging() - self.logger.debug("Starting OutputPlugin for sample '%s' with output '%s'" % (self._sample.name, self._sample.outputMode)) + self.logger.debug( + "Starting OutputPlugin for sample '%s' with output '%s'" % (self._sample.name, self._sample.outputMode)) self._queue = deque([]) self.output_counter = output_counter def __str__(self): """Only used for debugging, outputs a pretty printed representation of this output""" # Eliminate recursive going back to parent - temp = dict([ (key, value) for (key, value) in self.__dict__.items() if key != '_c']) + # temp = dict([(key, value) for (key, value) in self.__dict__.items() if key != '_c']) # return pprint.pformat(temp) return "" @@ -55,4 +58,4 @@ def run(self): def load(): - return OutputPlugin \ No newline at end of file + return OutputPlugin diff --git a/splunk_eventgen/lib/plugins/generator/default.py b/splunk_eventgen/lib/plugins/generator/default.py index 52bafe19..ed106e39 100644 --- a/splunk_eventgen/lib/plugins/generator/default.py +++ b/splunk_eventgen/lib/plugins/generator/default.py @@ -1,11 +1,12 @@ -# TODO Sample object now incredibly overloaded and not threadsafe. Need to make it threadsafe and make it simpler to get a -# copy of whats needed without the whole object. +# TODO: Sample object is incredibly overloaded and not threadsafe. Need to make it simpler to get a copy without the +# whole object get a copy of whats needed without the whole object. from __future__ import division -from generatorplugin import GeneratorPlugin -import datetime, time + +import datetime import random -from eventgentimestamp import EventgenTimestamp + +from generatorplugin import GeneratorPlugin class DefaultGenerator(GeneratorPlugin): @@ -13,27 +14,29 @@ def __init__(self, sample): GeneratorPlugin.__init__(self, sample) def gen(self, count, earliest, latest, samplename=None): - s = self._sample - - self.logger.debug("Generating sample '%s' in app '%s' with count %d, et: '%s', lt '%s'" % (self._sample.name, self._sample.app, count, earliest, latest)) + self.logger.debug("Generating sample '%s' in app '%s' with count %d, et: '%s', lt '%s'" % + (self._sample.name, self._sample.app, count, earliest, latest)) startTime = datetime.datetime.now() # If we're random, fill random events from sampleDict into eventsDict if self._sample.randomizeEvents: - eventsDict = [ ] + eventsDict = [] sdlen = len(self._sample.sampleDict) - self.logger.debugv("Random filling eventsDict for sample '%s' in app '%s' with %d events" % (self._sample.name, self._sample.app, count)) - # Count is -1, replay the whole file, but in randomizeEvents I think we'd want it to actually + self.logger.debugv("Random filling eventsDict for sample '%s' in app '%s' with %d events" % + (self._sample.name, self._sample.app, count)) + # Count is -1, replay the whole file, but in randomizeEvents I think we'd want it to actually # just put as many events as there are in the file if count == -1: count = sdlen while len(eventsDict) < count: - eventsDict.append(self._sample.sampleDict[random.randint(0, sdlen-1)]) + eventsDict.append(self._sample.sampleDict[random.randint(0, sdlen - 1)]) # If we're bundlelines, create count copies of the sampleDict elif self._sample.bundlelines: - eventsDict = [ ] - self.logger.debugv("Bundlelines, filling eventsDict for sample '%s' in app '%s' with %d copies of sampleDict" % (self._sample.name, self._sample.app, count)) + eventsDict = [] + self.logger.debugv( + "Bundlelines, filling eventsDict for sample '%s' in app '%s' with %d copies of sampleDict" % + (self._sample.name, self._sample.app, count)) for x in xrange(count): eventsDict.extend(self._sample.sampleDict) @@ -45,9 +48,11 @@ def gen(self, count, earliest, latest, samplename=None): count = len(self._sample.sampleDict) eventsDict = self._sample.sampleDict[0:count] - ## Continue to fill events array until len(events) == count + # Continue to fill events array until len(events) == count if len(eventsDict) < count: - self.logger.debugv("Events fill for sample '%s' in app '%s' less than count (%s vs. %s); continuing fill" % (self._sample.name, self._sample.app, len(eventsDict), count) ) + self.logger.debugv( + "Events fill for sample '%s' in app '%s' less than count (%s vs. %s); continuing fill" % + (self._sample.name, self._sample.app, len(eventsDict), count)) self.logger.debugv("Current eventsDict: %s" % eventsDict) # run a modulus on the size of the eventdict to figure out what the last event was. Populate to count # from there. @@ -57,9 +62,11 @@ def gen(self, count, earliest, latest, samplename=None): nextEventToUse = self._sample.sampleDict[len(eventsDict) % len(self._sample.sampleDict)] self.logger.debugv("Next event to add: %s" % nextEventToUse) eventsDict.append(nextEventToUse) - self.logger.debugv("Events fill complete for sample '%s' in app '%s' length %d" % (self._sample.name, self._sample.app, len(eventsDict))) + self.logger.debugv("Events fill complete for sample '%s' in app '%s' length %d" % + (self._sample.name, self._sample.app, len(eventsDict))) GeneratorPlugin.build_events(self, eventsDict, startTime, earliest, latest) + def load(): return DefaultGenerator diff --git a/splunk_eventgen/lib/plugins/generator/jinja.py b/splunk_eventgen/lib/plugins/generator/jinja.py index 52f3e63c..96af5c6f 100644 --- a/splunk_eventgen/lib/plugins/generator/jinja.py +++ b/splunk_eventgen/lib/plugins/generator/jinja.py @@ -1,20 +1,21 @@ from __future__ import division + import datetime -import time import os import random -try: - import ujson as json -except: - import json as json +import time + from jinja2 import nodes from jinja2.ext import Extension from generatorplugin import GeneratorPlugin +try: + import ujson as json +except: + import json as json class CantFindTemplate(Exception): - def __init__(self, msg): """Exception raised when we / Jinja can't find the template @@ -23,9 +24,7 @@ def __init__(self, msg): self.msg = msg super(CantFindTemplate, self).__init__(msg) - class CantProcessTemplate(Exception): - def __init__(self, msg): """Exception raised when we / Jinja can't find the template @@ -41,8 +40,8 @@ class JinjaTime(Extension): @staticmethod def _get_time_slice(earliest, latest, slices, target_slice, slice_type="lower"): """ - This method will take a time block bounded by "earliest and latest", and a slice. It'll then divide the time - in sections and return a tuple with 3 arguments, the lower bound, the higher bound, and the target in the middle. + This method will take a time block bounded by "earliest and latest", and a slice. It'll then divide the time in + sections and return a tuple with 3 arguments, the lower bound, the higher bound, and the target in the middle. :param earliest (in epoch): :param latest (in epoch): :param slices: @@ -62,12 +61,12 @@ def _get_time_slice(earliest, latest, slices, target_slice, slice_type="lower"): if slice_type == "lower": slice_time = slice_start elif slice_type == "middle": - slice_time = slice_start + (slice_size/2) + slice_time = slice_start + (slice_size / 2) elif slice_type == "upper": slice_time = slice_end elif slice_type == "random": - start = int(slice_start*100) - end = int(slice_end*100) + start = int(slice_start * 100) + end = int(slice_end * 100) if start == end: slice_time = end * 0.01 else: @@ -93,7 +92,8 @@ def _time_slice_formatted(self, earliest, latest, count, slices, date_format='%Y def _time_slice_epoch(self, earliest, latest, count, slices, date_format=None): slice_start, slice_end, slice_size, slice_time = \ - self._get_time_slice(earliest=earliest, latest=latest, slices=slices, target_slice=count, slice_type="lower") + self._get_time_slice(earliest=earliest, latest=latest, slices=slices, target_slice=count, + slice_type="lower") return slice_time @staticmethod @@ -106,17 +106,14 @@ def _output_var(var_value, lineno): return nodes.Output([var_value], lineno=lineno) def parse(self, parser): - target_var_name = { - "time_now": "time_now", - "time_slice": "time_target" - } + target_var_name = {"time_now": "time_now", "time_slice": "time_target"} tag = parser.stream.current.value name_base = target_var_name[tag] lineno = parser.stream.next().lineno args, kwargs = self.parse_args(parser) task_list = [] - epoch_name = name_base+"_epoch" - formatted_name = name_base+"_formatted" + epoch_name = name_base + "_epoch" + formatted_name = name_base + "_formatted" target_epoch_method = "_{0}_epoch".format(tag) target_formatted_method = "_{0}_formatted".format(tag) epoch_call = self.call_method(target_epoch_method, args=args, kwargs=kwargs, lineno=lineno) @@ -139,8 +136,7 @@ def parse_args(self, parser): kwargs.append(nodes.Keyword(key, value, lineno=value.lineno)) else: if kwargs: - parser.fail('Invalid argument syntax for WrapExtension tag', - parser.stream.current.lineno) + parser.fail('Invalid argument syntax for WrapExtension tag', parser.stream.current.lineno) args.append(parser.parse_expression()) require_comma = True return args, kwargs @@ -212,11 +208,10 @@ def gen(self, count, earliest, latest, samplename=None): if not hasattr(self._sample, "jinja_target_template"): raise CantFindTemplate("Template to load not specified in eventgen conf for stanza. Skipping Stanza") jinja_env = Environment( - loader=FileSystemLoader([target_template_dir, working_dir, template_dir], encoding='utf-8', followlinks=False), - extensions=['jinja2.ext.do', 'jinja2.ext.with_', 'jinja2.ext.loopcontrols', JinjaTime], - line_statement_prefix="#", - line_comment_prefix="##" - ) + loader=FileSystemLoader([target_template_dir, working_dir, template_dir], encoding='utf-8', + followlinks=False), extensions=[ + 'jinja2.ext.do', 'jinja2.ext.with_', 'jinja2.ext.loopcontrols', JinjaTime], + line_statement_prefix="#", line_comment_prefix="##") jinja_loaded_template = jinja_env.get_template(str(self._sample.jinja_target_template)) if hasattr(self._sample, 'jinja_variables'): @@ -227,36 +222,40 @@ def gen(self, count, earliest, latest, samplename=None): jinja_loaded_vars["eventgen_count"] = self.current_count jinja_loaded_vars["eventgen_maxcount"] = self.target_count jinja_loaded_vars["eventgen_earliest"] = self.earliest - self.earliest_epoch = (self.earliest - datetime.datetime(1970,1,1)).total_seconds() + self.earliest_epoch = (self.earliest - datetime.datetime(1970, 1, 1)).total_seconds() jinja_loaded_vars["eventgen_earliest_epoch"] = self.earliest_epoch jinja_loaded_vars["eventgen_latest"] = self.latest - jinja_loaded_vars["eventgen_latest_epoch"] = (self.latest - datetime.datetime(1970,1,1)).total_seconds() - self.latest_epoch = (self.latest - datetime.datetime(1970,1,1)).total_seconds() + jinja_loaded_vars["eventgen_latest_epoch"] = (self.latest - datetime.datetime(1970, 1, 1)).total_seconds() + self.latest_epoch = (self.latest - datetime.datetime(1970, 1, 1)).total_seconds() while self.current_count < self.target_count: self.end_of_cycle = False jinja_loaded_vars["eventgen_count"] = self.current_count jinja_loaded_vars["eventgen_target_time_earliest"], jinja_loaded_vars["eventgen_target_time_latest"], \ - jinja_loaded_vars["eventgen_target_time_slice_size"], jinja_loaded_vars["eventgen_target_time_epoch"] = \ - JinjaTime._get_time_slice(self.earliest_epoch, self.latest_epoch, self.target_count, self.current_count, slice_type="random") + jinja_loaded_vars["eventgen_target_time_slice_size"], \ + jinja_loaded_vars["eventgen_target_time_epoch"] = \ + JinjaTime._get_time_slice(self.earliest_epoch, self.latest_epoch, self.target_count, + self.current_count, slice_type="random") self.jinja_stream = jinja_loaded_template.stream(jinja_loaded_vars) lines_out = [] try: for line in self.jinja_stream: if line != "\n": - #TODO: Time can be supported by self._sample.timestamp, should probably set that up in this logic. + # TODO: Time can be supported by self._sample.timestamp, should probably set that up here. try: target_line = json.loads(line) except ValueError as e: self.logger.error("Unable to parse Jinja's return. Line: {0}".format(line)) self.logger.error("Parse Failure Reason: {0}".format(e.message)) - self.logger.error("Please note, you must meet the requirements for json.loads in python if you have not installed ujson. Native python does not support multi-line events.") + self.logger.error( + "Please note, you must meet the requirements for json.loads in python if you have" + + "not installed ujson. Native python does not support multi-line events.") continue current_line_keys = target_line.keys() if "_time" not in current_line_keys: - #TODO: Add a custom exception here + # TODO: Add a custom exception here raise Exception("No _time field supplied, please add time to your jinja template.") if "_raw" not in current_line_keys: - #TODO: Add a custom exception here + # TODO: Add a custom exception here raise Exception("No _raw field supplied, please add time to your jinja template.") if "host" not in current_line_keys: target_line["host"] = self._sample.host @@ -281,7 +280,7 @@ def gen(self, count, earliest, latest, samplename=None): timeDiffFrac = "%d.%06d" % (timeDiff.seconds, timeDiff.microseconds) self.logger.debugv("Interval complete, flushing feed") self._out.flush(endOfInterval=True) - self.logger.info("Generation of sample '%s' completed in %s seconds." % (self._sample.name, timeDiffFrac) ) + self.logger.info("Generation of sample '%s' completed in %s seconds." % (self._sample.name, timeDiffFrac)) return 0 except Exception as e: self.logger.exception(e) diff --git a/splunk_eventgen/lib/plugins/generator/perdayvolumegenerator.py b/splunk_eventgen/lib/plugins/generator/perdayvolumegenerator.py index 7e91948c..c58f7bae 100644 --- a/splunk_eventgen/lib/plugins/generator/perdayvolumegenerator.py +++ b/splunk_eventgen/lib/plugins/generator/perdayvolumegenerator.py @@ -1,18 +1,21 @@ from __future__ import division -from generatorplugin import GeneratorPlugin -import datetime, time + +import datetime import random +from generatorplugin import GeneratorPlugin + class PerDayVolumeGenerator(GeneratorPlugin): def __init__(self, sample): GeneratorPlugin.__init__(self, sample) - #TODO: Make this work with replay mode. + # TODO: Make this work with replay mode. def gen(self, count, earliest, latest, samplename=None): # count in this plugin is a measurement of byteself._sample. size = count - self.logger.debug("PerDayVolumeGenerator Called with a Size of: %s with Earliest: %s and Latest: %s" % (size, earliest, latest)) + self.logger.debug("PerDayVolumeGenerator Called with a Size of: %s with Earliest: %s and Latest: %s" % + (size, earliest, latest)) # very similar to the default generator. only difference is we go by size instead of count. try: self._sample.loadSample() @@ -21,7 +24,8 @@ def gen(self, count, earliest, latest, samplename=None): self.logger.error("Error loading sample file for sample '%s'" % self._sample.name) return - self.logger.debug("Generating sample '%s' in app '%s' with count %d, et: '%s', lt '%s'" % (self._sample.name, self._sample.app, size, earliest, latest)) + self.logger.debug("Generating sample '%s' in app '%s' with count %d, et: '%s', lt '%s'" % + (self._sample.name, self._sample.app, size, earliest, latest)) startTime = datetime.datetime.now() # Create a counter for the current byte size of the read in samples @@ -33,15 +37,18 @@ def gen(self, count, earliest, latest, samplename=None): eventsDict = [] if self._sample.randomizeEvents: sdlen = len(updated_sample_dict) - self.logger.debugv("Random filling eventsDict for sample '%s' in app '%s' with %d bytes" % (self._sample.name, self._sample.app, size)) + self.logger.debugv("Random filling eventsDict for sample '%s' in app '%s' with %d bytes" % + (self._sample.name, self._sample.app, size)) while currentSize < size: - currentevent = updated_sample_dict[random.randint(0, sdlen-1)] + currentevent = updated_sample_dict[random.randint(0, sdlen - 1)] eventsDict.append(currentevent) currentSize += len(currentevent['_raw']) # If we're bundlelines, create count copies of the sampleDict elif self._sample.bundlelines: - self.logger.debugv("Bundlelines, filling eventsDict for sample '%s' in app '%s' with %d copies of sampleDict" % (self._sample.name, self._sample.app, size)) + self.logger.debugv( + "Bundlelines, filling eventsDict for sample '%s' in app '%s' with %d copies of sampleDict" % + (self._sample.name, self._sample.app, size)) while currentSize <= size: sizeofsample = sum(len(sample['_raw']) for sample in updated_sample_dict) eventsDict.extend(updated_sample_dict) @@ -62,19 +69,22 @@ def gen(self, count, earliest, latest, samplename=None): sizeremaining = size - currentreadsize targetlinesize = len(updated_sample_dict[targetline]['_raw']) if size < targetlinesize: - self.logger.error("Size is too small for sample {}. For this interval, we need {} bytes but size of one event is {} bytes.".format(self._sample.name, size, targetlinesize)) + self.logger.error( + "Size is too small for sample {}. We need {} bytes but size of one event is {} bytes.".format( + self._sample.name, size, targetlinesize)) break - if targetlinesize <= sizeremaining or targetlinesize*.9 <= sizeremaining: + if targetlinesize <= sizeremaining or targetlinesize * .9 <= sizeremaining: currentreadsize += targetlinesize eventsDict.append(updated_sample_dict[targetline]) else: break linecount += 1 - self.logger.debugv("Events fill complete for sample '%s' in app '%s' length %d" % (self._sample.name, self._sample.app, len(eventsDict))) + self.logger.debugv("Events fill complete for sample '%s' in app '%s' length %d" % + (self._sample.name, self._sample.app, len(eventsDict))) # Ignore token replacement here because we completed it at the beginning of event generation GeneratorPlugin.build_events(self, eventsDict, startTime, earliest, latest, ignore_tokens=True) def load(): - return PerDayVolumeGenerator \ No newline at end of file + return PerDayVolumeGenerator diff --git a/splunk_eventgen/lib/plugins/generator/replay.py b/splunk_eventgen/lib/plugins/generator/replay.py index 8854f392..5f1a6900 100644 --- a/splunk_eventgen/lib/plugins/generator/replay.py +++ b/splunk_eventgen/lib/plugins/generator/replay.py @@ -1,12 +1,12 @@ # TODO Add timestamp detection for common timestamp format from __future__ import division -from generatorplugin import GeneratorPlugin -import datetime, time -import re -from eventgentimestamp import EventgenTimestamp +import datetime +import time +from eventgentimestamp import EventgenTimestamp +from generatorplugin import GeneratorPlugin class ReplayGenerator(GeneratorPlugin): @@ -22,14 +22,12 @@ def __init__(self, sample): self._currentevent = 0 self._timeSinceSleep = datetime.timedelta() - self._times = [ ] - - + self._times = [] def set_time_and_send(self, rpevent, event_time, earliest, latest): # temporary time append rpevent['_raw'] = rpevent['_raw'][:-1] - rpevent['_time'] = (event_time - datetime.datetime(1970,1,1)).total_seconds() + rpevent['_time'] = (event_time - datetime.datetime(1970, 1, 1)).total_seconds() event = rpevent['_raw'] @@ -38,10 +36,10 @@ def set_time_and_send(self, rpevent, event_time, earliest, latest): # picked from a random line in that file mvhash = {} - ## Iterate tokens + # Iterate tokens for token in self._sample.tokens: token.mvhash = mvhash - if token.replacementType in ['timestamp', 'replaytimestamp'] : + if token.replacementType in ['timestamp', 'replaytimestamp']: event = token.replace(event, et=event_time, lt=event_time, s=self._sample) else: event = token.replace(event, s=self._sample) @@ -68,7 +66,8 @@ def gen(self, count, earliest, latest, samplename=None): self.backfill_time = self._sample.get_backfill_time(self.current_time) if not self._sample.backfill or self._sample.backfilldone: - self.backfill_time = EventgenTimestamp.get_random_timestamp_backfill(earliest, latest, self._sample.earliest, self._sample.latest) + self.backfill_time = EventgenTimestamp.get_random_timestamp_backfill( + earliest, latest, self._sample.earliest, self._sample.latest) for line in self._sample.get_loaded_sample(): # Add newline to a raw line if necessary @@ -81,27 +80,29 @@ def gen(self, count, earliest, latest, samplename=None): hostRegex = line.get('hostRegex', self._sample.hostRegex) source = line.get('source', self._sample.source) sourcetype = line.get('sourcetype', self._sample.sourcetype) - rpevent = {'_raw': line['_raw'], 'index': index, 'host': host, 'hostRegex': hostRegex, - 'source': source, 'sourcetype': sourcetype} + rpevent = { + '_raw': line['_raw'], 'index': index, 'host': host, 'hostRegex': hostRegex, 'source': source, + 'sourcetype': sourcetype} except: if line[-1] != '\n': line += '\n' - rpevent = {'_raw': line, 'index': self._sample.index, 'host': self._sample.host, - 'hostRegex': self._sample.hostRegex, - 'source': self._sample.source, 'sourcetype': self._sample.sourcetype} + rpevent = { + '_raw': line, 'index': self._sample.index, 'host': self._sample.host, 'hostRegex': + self._sample.hostRegex, 'source': self._sample.source, 'sourcetype': self._sample.sourcetype} # If timestamp doesn't exist, the sample file should be fixed to include timestamp for every event. try: current_event_timestamp = self._sample.getTSFromEvent(rpevent[self._sample.timeField]) - except Exception as e: + except Exception: try: current_event_timestamp = self._sample.getTSFromEvent(line[self._sample.timeField]) - except Exception as e: + except Exception: try: - self.logger.debug("Sample timeField {} failed to locate. Trying to locate _time field.".format(self._sample.timeField)) + self.logger.debug("Sample timeField {} failed to locate. Trying to locate _time field.".format( + self._sample.timeField)) current_event_timestamp = self._sample.getTSFromEvent(line["_time"]) - except Exception as e: + except Exception: self.logger.exception("Extracting timestamp from an event failed.") continue @@ -130,5 +131,6 @@ def gen(self, count, earliest, latest, samplename=None): self._out.flush(endOfInterval=True) return + def load(): return ReplayGenerator diff --git a/splunk_eventgen/lib/plugins/generator/weblog.py b/splunk_eventgen/lib/plugins/generator/weblog.py index 39cda67f..b6c0e841 100755 --- a/splunk_eventgen/lib/plugins/generator/weblog.py +++ b/splunk_eventgen/lib/plugins/generator/weblog.py @@ -1,7 +1,9 @@ from __future__ import division -from generatorplugin import GeneratorPlugin -import time + import random +import time + +from generatorplugin import GeneratorPlugin class WeblogGenerator(GeneratorPlugin): @@ -30,25 +32,22 @@ def __init__(self, sample): def gen(self, count, earliest, latest, **kwargs): # logger.debug("weblog: external_ips_len: %s webhosts_len: %s useragents_len: %s webserverstatus_len: %s" % \ - # (self.external_ips_len, self.webhosts_len, self.useragents_len, self.webserverstatus_len)) - l = [ { '_raw': ('%s %s - - [%s] ' - + '"GET /product.screen?product_id=HolyGouda&JSESSIONID=SD3SL1FF7ADFF8 HTTP 1.1" ' - + '%s %s "http://shop.buttercupgames.com/cart.do?action=view&itemId=HolyGouda" ' - + '"%s" %s') % \ - (self.external_ips[random.randint(0, self.external_ips_len-1)], - self.webhosts[random.randint(0, self.webhosts_len-1)], - latest.strftime('%d/%b/%Y %H:%M:%S:%f'), - self.webserverstatus[random.randint(0, self.webserverstatus_len-1)], - random.randint(100, 1000), - self.useragents[random.randint(0, self.useragents_len-1)], - random.randint(200, 2000)), - 'index': self._sample.index, - 'sourcetype': self._sample.sourcetype, - 'host': self._sample.host, - 'source': self._sample.source, - '_time': int(time.mktime(latest.timetuple())) } for i in xrange(count) ] - - self._out.bulksend(l) + # (self.external_ips_len, self.webhosts_len, self.useragents_len, self.webserverstatus_len)) + payload = [{ + '_raw': + ('%s %s - - [%s] ' + '"GET /product.screen?product_id=HolyGouda&JSESSIONID=SD3SL1FF7ADFF8 HTTP 1.1" ' + + '%s %s "http://shop.buttercupgames.com/cart.do?action=view&itemId=HolyGouda" ' + '"%s" %s') % + (self.external_ips[random.randint(0, self.external_ips_len - 1)], self.webhosts[random.randint( + 0, self.webhosts_len - 1)], latest.strftime('%d/%b/%Y %H:%M:%S:%f'), + self.webserverstatus[random.randint(0, self.webserverstatus_len - 1)], random.randint(100, 1000), + self.useragents[random.randint(0, self.useragents_len - 1)], random.randint(200, 2000)), 'index': + self._sample.index, 'sourcetype': + self._sample.sourcetype, 'host': + self._sample.host, 'source': + self._sample.source, '_time': + int(time.mktime(latest.timetuple()))} for i in xrange(count)] + + self._out.bulksend(payload) return 0 diff --git a/splunk_eventgen/lib/plugins/generator/windbag.py b/splunk_eventgen/lib/plugins/generator/windbag.py index a8276382..90d2cd8a 100644 --- a/splunk_eventgen/lib/plugins/generator/windbag.py +++ b/splunk_eventgen/lib/plugins/generator/windbag.py @@ -1,8 +1,10 @@ from __future__ import division -from generatorplugin import GeneratorPlugin import datetime from datetime import timedelta +from generatorplugin import GeneratorPlugin + + class WindbagGenerator(GeneratorPlugin): def __init__(self, sample): GeneratorPlugin.__init__(self, sample) @@ -13,8 +15,8 @@ def gen(self, count, earliest, latest, samplename=None): count = 60 time_interval = timedelta.total_seconds((latest - earliest)) / count for i in xrange(count): - current_time_object = earliest + datetime.timedelta(0, time_interval*(i+1)) - msg = '{0} -0700 WINDBAG Event {1} of {2}'.format(current_time_object, (i+1), count) + current_time_object = earliest + datetime.timedelta(0, time_interval * (i + 1)) + msg = '{0} -0700 WINDBAG Event {1} of {2}'.format(current_time_object, (i + 1), count) self._out.send(msg) return 0 diff --git a/splunk_eventgen/lib/plugins/output/awss3.py b/splunk_eventgen/lib/plugins/output/awss3.py index 0e9210d9..223d90fa 100644 --- a/splunk_eventgen/lib/plugins/output/awss3.py +++ b/splunk_eventgen/lib/plugins/output/awss3.py @@ -1,16 +1,20 @@ from __future__ import division -from outputplugin import OutputPlugin + +import datetime +import logging +import threading +import uuid + import requests + +from outputplugin import OutputPlugin + try: import boto3 import botocore.exceptions boto_imported = True except ImportError: boto_imported = False -import uuid -import datetime -import threading -import logging def threaded(fn): @@ -31,18 +35,14 @@ class AwsS3OutputPlugin(OutputPlugin): name = 'awsS3' useOutputQueue = False # MAXQUEUELENGTH = 100 - validSettings = ['awsS3BucketName', 'awsS3CompressionType', - 'awsS3EventType', 'awsS3ObjectPrefix', - 'awsS3ObjectSuffix', 'awsRegion', 'awsKeyId', - 'awsSecretKey', 'awsS3EventPerKey'] - defaultableSettings = ['awsKeyId', 'awsSecretKey', 'awsS3EventType', - 'awsS3CompressionType', 'awsS3ObjectPrefix', - 'awsS3ObjectSuffix'] + validSettings = [ + 'awsS3BucketName', 'awsS3CompressionType', 'awsS3EventType', 'awsS3ObjectPrefix', 'awsS3ObjectSuffix', + 'awsRegion', 'awsKeyId', 'awsSecretKey', 'awsS3EventPerKey'] + defaultableSettings = [ + 'awsKeyId', 'awsSecretKey', 'awsS3EventType', 'awsS3CompressionType', 'awsS3ObjectPrefix', 'awsS3ObjectSuffix'] def __init__(self, sample, output_counter=None): - - # Override maxQueueLength to EventPerKey so that each flush # will generate one aws key if sample.awsS3EventPerKey: @@ -59,17 +59,15 @@ def __init__(self, sample, output_counter=None): # Bind passed in samples to the outputter. self.awsS3compressiontype = sample.awsS3CompressionType if hasattr( - sample, - 'awsS3CompressionType') and sample.awsS3CompressionType else None - self.awsS3eventtype = sample.awsS3EventType if hasattr( - sample, 'awsS3EventType') and sample.awsS3EventType else 'syslog' + sample, 'awsS3CompressionType') and sample.awsS3CompressionType else None + self.awsS3eventtype = sample.awsS3EventType if hasattr(sample, + 'awsS3EventType') and sample.awsS3EventType else 'syslog' self.awsS3objectprefix = sample.awsS3ObjectPrefix if hasattr( sample, 'awsS3ObjectPrefix') and sample.awsS3ObjectPrefix else "" self.awsS3objectsuffix = sample.awsS3ObjectSuffix if hasattr( sample, 'awsS3ObjectSuffix') and sample.awsS3ObjectSuffix else "" self.awsS3bucketname = sample.awsS3BucketName - self.logger.debug("Setting up the connection pool for %s in %s" % - (self._sample.name, self._app)) + self.logger.debug("Setting up the connection pool for %s in %s" % (self._sample.name, self._app)) self._client = None self._createConnections(sample) self.logger.debug("Finished init of awsS3 plugin.") @@ -77,11 +75,8 @@ def __init__(self, sample, output_counter=None): def _createConnections(self, sample): try: if hasattr(sample, 'awsKeyId') and hasattr(sample, 'awsSecretKey'): - self._client = boto3.client( - "s3", - region_name=sample.awsRegion, - aws_access_key_id=sample.awsKeyId, - aws_secret_access_key=sample.awsSecretKey) + self._client = boto3.client("s3", region_name=sample.awsRegion, aws_access_key_id=sample.awsKeyId, + aws_secret_access_key=sample.awsSecretKey) if self._client is None: msg = ''' [your_eventgen_stanza] @@ -89,10 +84,9 @@ def _createConnections(self, sample): awsSecretKey = YOUR_SECRET_KEY ''' - self.logger.error( - "Failed for init boto3 client: %s, you should define correct 'awsKeyId'\ + self.logger.error("Failed for init boto3 client: %s, you should define correct 'awsKeyId'\ and 'awsSecretKey' in eventgen conf %s" % msg) - raise + raise Exception(msg) else: self._client = boto3.client('s3', region_name=sample.awsRegion) except Exception as e: @@ -109,38 +103,29 @@ def _createConnections(self, sample): ''' self.logger.error("Failed for init boto3 client, you should create " - "'~/.aws/credentials' with credential info %s" % msg) + "'~/.aws/credentials' with credential info %s" % msg) raise self.logger.debug("Init conn done, conn = %s" % self._client) def _sendPayloads(self, payload): - currentreadsize = 0 - currentreadevent = 0 - stringpayload = [] - totalbytesexpected = 0 - totalbytessent = 0 numberevents = len(payload) self.logger.debug("Sending %s events to s3 key" % numberevents) self._transmitEvents(payload) def _transmitEvents(self, payloadstring): - self.logger.debug("Transmission called with payloadstring event number: %d " - % len(payloadstring)) + self.logger.debug("Transmission called with payloadstring event number: %d " % len(payloadstring)) records = "".join(payloadstring) # Different key prefix for different log type if self.awsS3eventtype == 'elbaccesslog': - s3keyname = self.awsS3objectprefix + datetime.datetime.utcnow( - ).strftime("%Y%m%dT%H%MZ") + '_' + str(uuid.uuid1( - )) + self.awsS3objectsuffix + s3keyname = self.awsS3objectprefix + datetime.datetime.utcnow().strftime("%Y%m%dT%H%MZ") + '_' + str( + uuid.uuid1()) + self.awsS3objectsuffix elif self.awsS3eventtype == 's3accesslog': - s3keyname = self.awsS3objectprefix + datetime.datetime.utcnow( - ).strftime("%Y-%m-%d-%H-%M-%S") + '-' + str(uuid.uuid1()).replace( - '-', '').upper()[0:15] + self.awsS3objectsuffix + s3keyname = self.awsS3objectprefix + datetime.datetime.utcnow().strftime("%Y-%m-%d-%H-%M-%S") + '-' + str( + uuid.uuid1()).replace('-', '').upper()[0:15] + self.awsS3objectsuffix else: - s3keyname = self.awsS3objectprefix + datetime.datetime.utcnow( - ).isoformat() + str(uuid.uuid1()) + self.awsS3objectsuffix - self.logger.debugv("Uploading %d events into s3 key: %s " % - (len(records), s3keyname)) + s3keyname = self.awsS3objectprefix + datetime.datetime.utcnow().isoformat() + str( + uuid.uuid1()) + self.awsS3objectsuffix + self.logger.debug("Uploading %d events into s3 key: %s " % (len(records), s3keyname)) if self.awsS3compressiontype == 'gz': import StringIO import gzip @@ -149,14 +134,11 @@ def _transmitEvents(self, payloadstring): f.write(records) records = out.getvalue() try: - response = self._client.put_object(Bucket=self.awsS3bucketname, - Key=s3keyname, - Body=records) - self.logger.debugv("response = %s" % response) + response = self._client.put_object(Bucket=self.awsS3bucketname, Key=s3keyname, Body=records) + self.logger.debug("response = %s" % response) except Exception as e: self.logger.error("Failed for exception: %s" % e) - self.logger.debugv("Failed sending events to payload: %s" % - (payloadstring)) + self.logger.debug("Failed sending events to payload: %s" % (payloadstring)) raise e def flush(self, q): @@ -167,12 +149,10 @@ def flush(self, q): self.logger.debug("Currently being called with %d events" % len(q)) for event in q: if event.get('_raw') is None: - self.logger.error( - 'failure outputting event, does not contain _raw') + self.logger.error('failure outputting event, does not contain _raw') else: payload.append(event['_raw']) - self.logger.debug( - "Finished processing events, sending all to AWS S3") + self.logger.debug("Finished processing events, sending all to AWS S3") self._sendPayloads(payload) except Exception as e: import traceback diff --git a/splunk_eventgen/lib/plugins/output/devnull.py b/splunk_eventgen/lib/plugins/output/devnull.py index 70bbdde6..faf26a81 100755 --- a/splunk_eventgen/lib/plugins/output/devnull.py +++ b/splunk_eventgen/lib/plugins/output/devnull.py @@ -1,7 +1,10 @@ from __future__ import division -from outputplugin import OutputPlugin + import logging +from outputplugin import OutputPlugin + + class DevNullOutputPlugin(OutputPlugin): name = 'devnull' MAXQUEUELENGTH = 1000 @@ -21,6 +24,7 @@ def flush(self, q): def _setup_logging(self): self.logger = logging.getLogger('eventgen_devnullout') + def load(): """Returns an instance of the plugin""" return DevNullOutputPlugin diff --git a/splunk_eventgen/lib/plugins/output/file.py b/splunk_eventgen/lib/plugins/output/file.py index d04b23a1..3287c49d 100644 --- a/splunk_eventgen/lib/plugins/output/file.py +++ b/splunk_eventgen/lib/plugins/output/file.py @@ -1,9 +1,11 @@ # Note as implemented this plugin is not threadsafe, file should only be used with one output worker from __future__ import division -from outputplugin import OutputPlugin -import os + import logging +import os + +from outputplugin import OutputPlugin class FileOutputPlugin(OutputPlugin): @@ -11,28 +13,29 @@ class FileOutputPlugin(OutputPlugin): MAXQUEUELENGTH = 10 useOutputQueue = False - validSettings = [ 'fileMaxBytes', 'fileBackupFiles' ] - intSettings = [ 'fileMaxBytes', 'fileBackupFiles' ] + validSettings = ['fileMaxBytes', 'fileBackupFiles'] + intSettings = ['fileMaxBytes', 'fileBackupFiles'] def __init__(self, sample, output_counter=None): OutputPlugin.__init__(self, sample, output_counter) - if sample.fileName == None: + if sample.fileName is None: self.logger.error('outputMode file but file not specified for sample %s' % self._sample.name) raise ValueError('outputMode file but file not specified for sample %s' % self._sample.name) - + self._file = sample.pathParser(sample.fileName) self._fileMaxBytes = sample.fileMaxBytes self._fileBackupFiles = sample.fileBackupFiles self._fileHandle = open(self._file, 'a') self._fileLength = os.stat(self._file).st_size - self.logger.debug("Configured to log to '%s' with maxBytes '%s' with backupCount '%s'" % \ - (self._file, self._fileMaxBytes, self._fileBackupFiles)) + self.logger.debug("Configured to log to '%s' with maxBytes '%s' with backupCount '%s'" % + (self._file, self._fileMaxBytes, self._fileBackupFiles)) def flush(self, q): if len(q) > 0: - self.logger.debug("Flushing output for sample '%s' in app '%s' for queue '%s'" % (self._sample.name, self._app, self._sample.source)) + self.logger.debug("Flushing output for sample '%s' in app '%s' for queue '%s'" % + (self._sample.name, self._app, self._sample.source)) # Loop through all the messages and build the long string, write once for each flush # This may cause the file exceed the maxFileBytes a little bit but will greatly improve the performance @@ -52,19 +55,22 @@ def flush(self, q): if self._fileLength > self._fileMaxBytes: self._fileHandle.flush() self._fileHandle.close() - if os.path.exists(self._file+'.'+str(self._fileBackupFiles)): - self.logger.debug('File Output: Removing file: %s' % self._file+'.'+str(self._fileBackupFiles)) - os.unlink(self._file+'.'+str(self._fileBackupFiles)) + if os.path.exists(self._file + '.' + str(self._fileBackupFiles)): + self.logger.debug('File Output: Removing file: %s' % self._file + '.' + + str(self._fileBackupFiles)) + os.unlink(self._file + '.' + str(self._fileBackupFiles)) for x in range(1, self._fileBackupFiles)[::-1]: - self.logger.debug('File Output: Checking for file: %s' % self._file+'.'+str(x)) - if os.path.exists(self._file+'.'+str(x)): - self.logger.debug('File Output: Renaming file %s to %s' % (self._file+'.'+str(x), self._file+'.'+str(x+1))) - os.rename(self._file+'.'+str(x), self._file+'.'+str(x+1)) - os.rename(self._file, self._file+'.1') + self.logger.debug('File Output: Checking for file: %s' % self._file + '.' + str(x)) + if os.path.exists(self._file + '.' + str(x)): + self.logger.debug('File Output: Renaming file %s to %s' % (self._file + '.' + str(x), + self._file + '.' + str(x + 1))) + os.rename(self._file + '.' + str(x), self._file + '.' + str(x + 1)) + os.rename(self._file, self._file + '.1') self._fileHandle = open(self._file, 'w') self._fileLength = 0 except IndexError: - self.logger.warning("IndexError when writting for app '%s' sample '%s'" % (self._app, self._sample.name)) + self.logger.warning( + "IndexError when writting for app '%s' sample '%s'" % (self._app, self._sample.name)) if not self._fileHandle.closed: self._fileHandle.flush() @@ -75,6 +81,7 @@ def flush(self, q): def _setup_logging(self): self.logger = logging.getLogger('eventgen') + def load(): """Returns an instance of the plugin""" return FileOutputPlugin diff --git a/splunk_eventgen/lib/plugins/output/httpevent.py b/splunk_eventgen/lib/plugins/output/httpevent.py index 107371c5..81082a1c 100644 --- a/splunk_eventgen/lib/plugins/output/httpevent.py +++ b/splunk_eventgen/lib/plugins/output/httpevent.py @@ -1,8 +1,13 @@ from __future__ import division + +import logging +import random +import urllib + from outputplugin import OutputPlugin + try: import requests - import requests_futures from requests import Session from requests_futures.sessions import FuturesSession from concurrent.futures import ThreadPoolExecutor @@ -12,17 +17,17 @@ import ujson as json except: import json -import random -import urllib -import logging + class NoServers(Exception): - def __init__(self,*args,**kwargs): - Exception.__init__(self,*args,**kwargs) + def __init__(self, *args, **kwargs): + Exception.__init__(self, *args, **kwargs) + class BadConnection(Exception): - def __init__(self,*args,**kwargs): - Exception.__init__(self,*args,**kwargs) + def __init__(self, *args, **kwargs): + Exception.__init__(self, *args, **kwargs) + class HTTPEventOutputPlugin(OutputPlugin): ''' @@ -30,9 +35,9 @@ class HTTPEventOutputPlugin(OutputPlugin): to splunk through the HTTP event input. In order to use this output plugin, you will need to supply an attribute 'httpeventServers' as a valid json object. this json object should look like the following: - + {servers:[{ protocol:http/https, address:127.0.0.1, port:8088, key:12345-12345-123123123123123123}]} - + ''' name = 'httpevent' MAXQUEUELENGTH = 1000 @@ -44,11 +49,11 @@ class HTTPEventOutputPlugin(OutputPlugin): def __init__(self, sample, output_counter=None): OutputPlugin.__init__(self, sample, output_counter) - #TODO: make workers a param that can be set in eventgen.conf + # TODO: make workers a param that can be set in eventgen.conf def _setup_REST_workers(self, session=None, workers=10): - #disable any "requests" warnings + # disable any "requests" warnings requests.packages.urllib3.disable_warnings() - #Bind passed in samples to the outputter. + # Bind passed in samples to the outputter. self.lastsourcetype = None if not session: session = Session() @@ -67,8 +72,8 @@ def _urlencode(value): @staticmethod def _bg_convert_json(sess, resp): ''' - Takes a futures session object, and will set the data to a parsed json output. Use this as a background task - for the sesssion queue. Example: future = session.get('http://httpbin.org/get', background_callback=_bg_convert_json) + Takes a futures session object, and sets the data to a parsed json output. Use this as a background task for the + session queue. Example: future = session.get('http://httpbin.org/get', background_callback=_bg_convert_json) :param sess: futures session object. Automatically called on a background_callback as aruguments. :param resp: futures resp object. Automatically called on a background_callback as aruguments. :return: @@ -83,12 +88,14 @@ def _bg_convert_json(sess, resp): def updateConfig(self, config): OutputPlugin.updateConfig(self, config) try: - if hasattr(self.config, 'httpeventServers') == False: + if hasattr(self.config, 'httpeventServers') is False: if hasattr(self._sample, 'httpeventServers'): self.config.httpeventServers = self._sample.httpeventServers else: - self.logger.error('outputMode httpevent but httpeventServers not specified for sample %s' % self._sample.name) - raise NoServers('outputMode httpevent but httpeventServers not specified for sample %s' % self._sample.name) + self.logger.error( + 'outputMode httpevent but httpeventServers not specified for sample %s' % self._sample.name) + raise NoServers( + 'outputMode httpevent but httpeventServers not specified for sample %s' % self._sample.name) # set default output mode to round robin if hasattr(self.config, 'httpeventOutputMode') and self.config.httpeventOutputMode: self.httpeventoutputmode = config.httpeventOutputMode @@ -106,9 +113,9 @@ def updateConfig(self, config): self.httpeventmaxsize = 10000 self.logger.debug("Currentmax size: %s " % self.httpeventmaxsize) if isinstance(config.httpeventServers, str): - self.httpeventServers = json.loads(config.httpeventServers) + self.httpeventServers = json.loads(config.httpeventServers) else: - self.httpeventServers = config.httpeventServers + self.httpeventServers = config.httpeventServers self.logger.debug("Setting up the connection pool for %s in %s" % (self._sample.name, self._app)) self.createConnections() self.logger.debug("Pool created.") @@ -116,27 +123,40 @@ def updateConfig(self, config): except Exception as e: self.logger.exception(e) - def createConnections(self): self.serverPool = [] if self.httpeventServers: for server in self.httpeventServers.get('servers'): if not server.get('address'): - self.logger.error('requested a connection to a httpevent server, but no address specified for sample %s' % self._sample.name) - raise ValueError('requested a connection to a httpevent server, but no address specified for sample %s' % self._sample.name) + self.logger.error( + 'requested a connection to a httpevent server, but no address specified for sample %s' % + self._sample.name) + raise ValueError( + 'requested a connection to a httpevent server, but no address specified for sample %s' % + self._sample.name) if not server.get('port'): - self.logger.error('requested a connection to a httpevent server, but no port specified for server %s' % server) - raise ValueError('requested a connection to a httpevent server, but no port specified for server %s' % server) + self.logger.error( + 'requested a connection to a httpevent server, but no port specified for server %s' % server) + raise ValueError( + 'requested a connection to a httpevent server, but no port specified for server %s' % server) if not server.get('key'): - self.logger.error('requested a connection to a httpevent server, but no key specified for server %s' % server) - raise ValueError('requested a connection to a httpevent server, but no key specified for server %s' % server) + self.logger.error( + 'requested a connection to a httpevent server, but no key specified for server %s' % server) + raise ValueError( + 'requested a connection to a httpevent server, but no key specified for server %s' % server) if not ((server.get('protocol') == 'http') or (server.get('protocol') == 'https')): - self.logger.error('requested a connection to a httpevent server, but no protocol specified for server %s' % server) - raise ValueError('requested a connection to a httpevent server, but no protocol specified for server %s' % server) - self.logger.debug("Validation Passed, Creating a requests object for server: %s" % server.get('address')) + self.logger.error( + 'requested a connection to a httpevent server, but no protocol specified for server %s' % + server) + raise ValueError( + 'requested a connection to a httpevent server, but no protocol specified for server %s' % + server) + self.logger.debug( + "Validation Passed, Creating a requests object for server: %s" % server.get('address')) setserver = {} - setserver['url'] = "%s://%s:%s/services/collector" % (server.get('protocol'), server.get('address'), server.get('port')) + setserver['url'] = "%s://%s:%s/services/collector" % (server.get('protocol'), server.get('address'), + server.get('port')) setserver['header'] = "Splunk %s" % server.get('key') self.logger.debug("Adding server set to pool, server: %s" % setserver) self.serverPool.append(setserver) @@ -151,15 +171,15 @@ def _sendHTTPEvents(self, payload): numberevents = len(payload) self.logger.debug("Sending %s events to splunk" % numberevents) for line in payload: - self.logger.debugv("line: %s " % line) + self.logger.debug("line: %s " % line) targetline = json.dumps(line) - self.logger.debugv("targetline: %s " % targetline) + self.logger.debug("targetline: %s " % targetline) targetlinesize = len(targetline) totalbytesexpected += targetlinesize if (int(currentreadsize) + int(targetlinesize)) <= int(self.httpeventmaxsize): stringpayload = stringpayload + targetline currentreadsize = currentreadsize + targetlinesize - self.logger.debugv("stringpayload: %s " % stringpayload) + self.logger.debug("stringpayload: %s " % stringpayload) else: self.logger.debug("Max size for payload hit, sending to splunk then continuing.") try: @@ -173,7 +193,9 @@ def _sendHTTPEvents(self, payload): else: try: totalbytessent += len(stringpayload) - self.logger.debug("End of for loop hit for sending events to splunk, total bytes sent: %s ---- out of %s -----" % (totalbytessent, totalbytesexpected)) + self.logger.debug( + "End of for loop hit for sending events to splunk, total bytes sent: %s ---- out of %s -----" % + (totalbytessent, totalbytesexpected)) self._transmitEvents(stringpayload) except Exception as e: self.logger.exception(e) @@ -181,7 +203,7 @@ def _sendHTTPEvents(self, payload): def _transmitEvents(self, payloadstring): targetServer = [] - self.logger.debugv("Transmission called with payloadstring: %s " % payloadstring) + self.logger.debug("Transmission called with payloadstring: %s " % payloadstring) if self.httpeventoutputmode == "mirror": targetServer = self.serverPool else: @@ -194,12 +216,15 @@ def _transmitEvents(self, payloadstring): headers['content-type'] = 'application/json' try: payloadsize = len(payloadstring) - #response = requests.post(url, data=payloadstring, headers=headers, verify=False) - self.active_sessions.append(self.session.post(url=url, data=payloadstring, headers=headers, verify=False)) + # response = requests.post(url, data=payloadstring, headers=headers, verify=False) + self.active_sessions.append( + self.session.post(url=url, data=payloadstring, headers=headers, verify=False)) except Exception as e: self.logger.error("Failed for exception: %s" % e) - self.logger.error("Failed sending events to url: %s sourcetype: %s size: %s" % (url, self.lastsourcetype, payloadsize)) - self.logger.debugv("Failed sending events to url: %s headers: %s payload: %s" % (url, headers, payloadstring)) + self.logger.error("Failed sending events to url: %s sourcetype: %s size: %s" % + (url, self.lastsourcetype, payloadsize)) + self.logger.debug( + "Failed sending events to url: %s headers: %s payload: %s" % (url, headers, payloadstring)) raise e def flush(self, q): @@ -208,39 +233,37 @@ def flush(self, q): if len(q) > 0: try: payload = [] - lastsourcetype = "" - payloadsize = 0 self.logger.debug("Currently being called with %d events" % len(q)) for event in q: - self.logger.debugv("HTTPEvent proccessing event: %s" % event) + self.logger.debug("HTTPEvent proccessing event: %s" % event) payloadFragment = {} - if event.get('_raw') == None or event['_raw'] == "\n": + if event.get('_raw') is None or event['_raw'] == "\n": self.logger.error('failure outputting event, does not contain _raw') else: - self.logger.debugv("Event contains _raw, attempting to process...") + self.logger.debug("Event contains _raw, attempting to process...") payloadFragment['event'] = event['_raw'] if event.get('source'): - self.logger.debugv("Event contains source, adding to httpevent event") + self.logger.debug("Event contains source, adding to httpevent event") payloadFragment['source'] = event['source'] if event.get('sourcetype'): - self.logger.debugv("Event contains sourcetype, adding to httpevent event") + self.logger.debug("Event contains sourcetype, adding to httpevent event") payloadFragment['sourcetype'] = event['sourcetype'] self.lastsourcetype = event['sourcetype'] if event.get('host'): - self.logger.debugv("Event contains host, adding to httpevent event") + self.logger.debug("Event contains host, adding to httpevent event") payloadFragment['host'] = event['host'] if event.get('_time'): # make sure _time can be an epoch timestamp try: float(event.get("_time")) - self.logger.debugv("Event contains _time, adding to httpevent event") + self.logger.debug("Event contains _time, adding to httpevent event") payloadFragment['time'] = event['_time'] except: self.logger.error("Timestamp not in epoch format, ignoring event: {0}".format(event)) if event.get('index'): - self.logger.debugv("Event contains index, adding to httpevent event") + self.logger.debug("Event contains index, adding to httpevent event") payloadFragment['index'] = event['index'] - self.logger.debugv("Full payloadFragment: %s" % json.dumps(payloadFragment)) + self.logger.debug("Full payloadFragment: %s" % json.dumps(payloadFragment)) payload.append(payloadFragment) self.logger.debug("Finished processing events, sending all to splunk") self._sendHTTPEvents(payload) @@ -250,8 +273,10 @@ def flush(self, q): if not response.raise_for_status(): self.logger.debug("Payload successfully sent to httpevent server.") else: - self.logger.error("Server returned an error while trying to send, response code: %s" % response.status_code) - raise BadConnection("Server returned an error while sending, response code: %s" % response.status_code) + self.logger.error("Server returned an error while trying to send, response code: %s" % + response.status_code) + raise BadConnection( + "Server returned an error while sending, response code: %s" % response.status_code) else: self.logger.debug("Ignoring response from HTTP server, leaving httpevent outputter") except Exception as e: @@ -260,6 +285,7 @@ def flush(self, q): def _setup_logging(self): self.logger = logging.getLogger('eventgen_httpeventout') + def load(): """Returns an instance of the plugin""" return HTTPEventOutputPlugin diff --git a/splunk_eventgen/lib/plugins/output/modinput.py b/splunk_eventgen/lib/plugins/output/modinput.py index ac748396..cd2b792b 100644 --- a/splunk_eventgen/lib/plugins/output/modinput.py +++ b/splunk_eventgen/lib/plugins/output/modinput.py @@ -4,10 +4,13 @@ # from eventgenoutputtemplates import OutputTemplate from __future__ import division -from outputplugin import OutputPlugin + +import logging import sys from xml.sax.saxutils import escape -import logging + +from outputplugin import OutputPlugin + class ModInputOutputPlugin(OutputPlugin): name = 'modinput' @@ -45,6 +48,7 @@ def flush(self, q): def _setup_logging(self): self.logger = logging.getLogger('eventgen') + def load(): """Returns an instance of the plugin""" - return ModInputOutputPlugin \ No newline at end of file + return ModInputOutputPlugin diff --git a/splunk_eventgen/lib/plugins/output/s2s.py b/splunk_eventgen/lib/plugins/output/s2s.py index 26f132e3..6798dbcc 100644 --- a/splunk_eventgen/lib/plugins/output/s2s.py +++ b/splunk_eventgen/lib/plugins/output/s2s.py @@ -1,9 +1,10 @@ from __future__ import division -from outputplugin import OutputPlugin -import struct -import socket import logging +import socket +import struct + +from outputplugin import OutputPlugin class S2S: @@ -60,7 +61,7 @@ def _encode_string(self, tosend=''): by a null terminated string. """ tosend = str(tosend) - return struct.pack('!I%ds' % (len(tosend)+1), len(tosend)+1, tosend) + return struct.pack('!I%ds' % (len(tosend) + 1), len(tosend) + 1, tosend) def _encode_key_value(self, key='', value=''): """ @@ -74,30 +75,29 @@ def _encode_event(self, index='main', host='', source='', sourcetype='', _raw='_ # Create signature sig = self._encode_sig() - msg_size = len(struct.pack('!I', 0)) # size of unsigned 32 bit integer, which is the count of map entries + msg_size = len(struct.pack('!I', 0)) # size of unsigned 32 bit integer, which is the count of map entries maps = 1 # May not have these, so set them first encoded_source = False encoded_sourcetype = False encoded_host = False - encoded_index = False # Encode source if len(source) > 0: - encoded_source = self._encode_key_value('MetaData:Source', 'source::'+source) + encoded_source = self._encode_key_value('MetaData:Source', 'source::' + source) maps += 1 msg_size += len(encoded_source) # Encode sourcetype if len(sourcetype) > 0: - encoded_sourcetype = self._encode_key_value('MetaData:Sourcetype', 'sourcetype::'+sourcetype) + encoded_sourcetype = self._encode_key_value('MetaData:Sourcetype', 'sourcetype::' + sourcetype) maps += 1 msg_size += len(encoded_sourcetype) - + # Encode host if len(host) > 0: - encoded_host = self._encode_key_value('MetaData:Host', 'host::'+host) + encoded_host = self._encode_key_value('MetaData:Host', 'host::' + host) maps += 1 msg_size += len(encoded_host) @@ -105,7 +105,7 @@ def _encode_event(self, index='main', host='', source='', sourcetype='', _raw='_ encoded_index = self._encode_key_value('_MetaData:Index', index) maps += 1 msg_size += len(encoded_index) - + # Encode _raw encoded_raw = self._encode_key_value('_raw', _raw) msg_size += len(encoded_raw) @@ -124,7 +124,7 @@ def _encode_event(self, index='main', host='', source='', sourcetype='', _raw='_ msg_size += len(encoded_done) # Encode _time - if _time != None: + if _time is not None: encoded_time = self._encode_key_value('_time', _time) msg_size += len(encoded_time) maps += 1 @@ -163,6 +163,7 @@ def close(self): """ self.s.close() + class S2SOutputPlugin(OutputPlugin): name = 's2s' MAXQUEUELENGTH = 10 diff --git a/splunk_eventgen/lib/plugins/output/splunkstream.py b/splunk_eventgen/lib/plugins/output/splunkstream.py index 39fb8432..e258872c 100644 --- a/splunk_eventgen/lib/plugins/output/splunkstream.py +++ b/splunk_eventgen/lib/plugins/output/splunkstream.py @@ -1,10 +1,14 @@ from __future__ import division -from outputplugin import OutputPlugin -from xml.dom import minidom -from collections import deque -import httplib, httplib2 -import urllib + +import httplib import logging +import urllib +from collections import deque +from xml.dom import minidom + +import httplib2 + +from outputplugin import OutputPlugin class SplunkStreamOutputPlugin(OutputPlugin): @@ -29,24 +33,31 @@ def __init__(self, sample, output_counter=None): from eventgenconfig import Config globals()['c'] = Config() - self._splunkUrl, self._splunkMethod, self._splunkHost, self._splunkPort = c.getSplunkUrl(self._sample) + self._splunkUrl, self._splunkMethod, self._splunkHost, self._splunkPort = c.getSplunkUrl(self._sample) # noqa self._splunkUser = self._sample.splunkUser self._splunkPass = self._sample.splunkPass if not self._sample.sessionKey: try: myhttp = httplib2.Http(disable_ssl_certificate_validation=True) - self.logger.debug("Getting session key from '%s' with user '%s' and pass '%s'" % (self._splunkUrl + '/services/auth/login', self._splunkUser, self._splunkPass)) - response = myhttp.request(self._splunkUrl + '/services/auth/login', 'POST', - headers = {}, body=urllib.urlencode({'username': self._splunkUser, - 'password': self._splunkPass}))[1] - self._sample.sessionKey = minidom.parseString(response).getElementsByTagName('sessionKey')[0].childNodes[0].nodeValue + self.logger.debug("Getting session key from '%s' with user '%s' and pass '%s'" % + (self._splunkUrl + '/services/auth/login', self._splunkUser, self._splunkPass)) + response = myhttp.request( + self._splunkUrl + '/services/auth/login', 'POST', headers={}, body=urllib.urlencode({ + 'username': + self._splunkUser, 'password': + self._splunkPass}))[1] + self._sample.sessionKey = minidom.parseString(response).getElementsByTagName( + 'sessionKey')[0].childNodes[0].nodeValue self.logger.debug("Got new session for splunkstream, sessionKey '%s'" % self._sample.sessionKey) except: - self.logger.error("Error getting session key for non-SPLUNK_EMBEEDED for sample '%s'. Credentials are missing or wrong" % self._sample.name) - raise IOError("Error getting session key for non-SPLUNK_EMBEEDED for sample '%s'. Credentials are missing or wrong" % self._sample.name) + self.logger.error("Error getting session key for non-SPLUNK_EMBEEDED for sample '%s'." % + self._sample.name + " Credentials are missing or wrong") + raise IOError("Error getting session key for non-SPLUNK_EMBEEDED for sample '%s'." % self._sample.name + + "Credentials are missing or wrong") - self.logger.debug("Retrieved session key '%s' for Splunk session for sample %s'" % (self._sample.sessionKey, self._sample.name)) + self.logger.debug("Retrieved session key '%s' for Splunk session for sample %s'" % (self._sample.sessionKey, + self._sample.name)) def flush(self, q): if len(q) > 0: @@ -78,7 +89,8 @@ def flush(self, q): except KeyError: pass - self.logger.debug("Flushing output for sample '%s' in app '%s' for queue '%s'" % (self._sample.name, self._app, self._sample.source)) + self.logger.debug("Flushing output for sample '%s' in app '%s' for queue '%s'" % + (self._sample.name, self._app, self._sample.source)) try: if self._splunkMethod == 'https': connmethod = httplib.HTTPSConnection @@ -111,11 +123,14 @@ def flush(self, q): msg = False splunkhttp.request("POST", url, streamout, headers) - self.logger.debug("POSTing to url %s on %s://%s:%s with sessionKey %s" \ - % (url, self._splunkMethod, self._splunkHost, self._splunkPort, self._sample.sessionKey)) + self.logger.debug( + "POSTing to url %s on %s://%s:%s with sessionKey %s" % + (url, self._splunkMethod, self._splunkHost, self._splunkPort, self._sample.sessionKey)) except httplib.HTTPException, e: - self.logger.error('Error connecting to Splunk for logging for sample %s. Exception "%s" Config: %s' % (self._sample.name, e.args, self)) + self.logger.error( + 'Error connecting to Splunk for logging for sample %s. Exception "%s" Config: %s' % + (self._sample.name, e.args, self)) raise IOError('Error connecting to Splunk for logging for sample %s' % self._sample) try: diff --git a/splunk_eventgen/lib/plugins/output/spool.py b/splunk_eventgen/lib/plugins/output/spool.py index cd478123..60a76d69 100644 --- a/splunk_eventgen/lib/plugins/output/spool.py +++ b/splunk_eventgen/lib/plugins/output/spool.py @@ -4,18 +4,21 @@ # from eventgenoutputtemplates import OutputTemplate from __future__ import division -from outputplugin import OutputPlugin -import time -import os + import logging +import os +import time + +from outputplugin import OutputPlugin + class SpoolOutputPlugin(OutputPlugin): useOutputQueue = True name = 'spool' MAXQUEUELENGTH = 10 - validSettings = [ 'spoolDir', 'spoolFile' ] - defaultableSettings = [ 'spoolDir', 'spoolFile' ] + validSettings = ['spoolDir', 'spoolFile'] + defaultableSettings = ['spoolDir', 'spoolFile'] _spoolDir = None _spoolFile = None @@ -28,7 +31,8 @@ def __init__(self, sample, output_counter=None): def flush(self, q): if len(q) > 0: - self.logger.debug("Flushing output for sample '%s' in app '%s' for queue '%s'" % (self._sample.name, self._app, self._sample.source)) + self.logger.debug("Flushing output for sample '%s' in app '%s' for queue '%s'" % + (self._sample.name, self._app, self._sample.source)) # Keep trying to open destination file as it might be touched by other processes data = ''.join(event['_raw'] for event in q if event.get('_raw')) while True: diff --git a/splunk_eventgen/lib/plugins/output/stdout.py b/splunk_eventgen/lib/plugins/output/stdout.py index 3edc44df..a0ea46e1 100644 --- a/splunk_eventgen/lib/plugins/output/stdout.py +++ b/splunk_eventgen/lib/plugins/output/stdout.py @@ -1,7 +1,10 @@ from __future__ import division -from outputplugin import OutputPlugin + import logging +from outputplugin import OutputPlugin + + class StdOutOutputPlugin(OutputPlugin): useOutputQueue = False name = 'stdout' @@ -17,6 +20,7 @@ def flush(self, q): def _setup_logging(self): self.logger = logging.getLogger('eventgen_stdout') + def load(): """Returns an instance of the plugin""" - return StdOutOutputPlugin \ No newline at end of file + return StdOutOutputPlugin diff --git a/splunk_eventgen/lib/plugins/output/syslogout.py b/splunk_eventgen/lib/plugins/output/syslogout.py index eb07a2e1..b1faad28 100644 --- a/splunk_eventgen/lib/plugins/output/syslogout.py +++ b/splunk_eventgen/lib/plugins/output/syslogout.py @@ -1,22 +1,28 @@ from __future__ import division + +import logging +import logging.handlers + from outputplugin import OutputPlugin -import logging, logging.handlers # Dict of flags to gate adding the syslogHandler only once to the given singleton logger loggerInitialized = {} + class SyslogOutOutputPlugin(OutputPlugin): useOutputQueue = True name = 'syslogout' MAXQUEUELENGTH = 10 - validSettings = [ 'syslogDestinationHost', 'syslogDestinationPort' ] - defaultableSettings = [ 'syslogDestinationHost', 'syslogDestinationPort' ] - intSettings = [ 'syslogDestinationPort' ] + validSettings = ['syslogDestinationHost', 'syslogDestinationPort'] + defaultableSettings = ['syslogDestinationHost', 'syslogDestinationPort'] + intSettings = ['syslogDestinationPort'] def __init__(self, sample, output_counter=None): OutputPlugin.__init__(self, sample, output_counter) - self._syslogDestinationHost = sample.syslogDestinationHost if hasattr(sample, 'syslogDestinationHost') and sample.syslogDestinationHost else '127.0.0.1' - self._syslogDestinationPort = sample.syslogDestinationPort if hasattr(sample, 'syslogDestinationPort') and sample.syslogDestinationPort else 1514 + self._syslogDestinationHost = sample.syslogDestinationHost if hasattr( + sample, 'syslogDestinationHost') and sample.syslogDestinationHost else '127.0.0.1' + self._syslogDestinationPort = sample.syslogDestinationPort if hasattr( + sample, 'syslogDestinationPort') and sample.syslogDestinationPort else 1514 loggerName = 'syslog' + sample.name self._l = logging.getLogger(loggerName) @@ -25,8 +31,9 @@ def __init__(self, sample, output_counter=None): global loggerInitialized # This class is instantiated at least once each interval. Since each logger with a given name is a singleton, # only add the syslog handler once instead of every interval. - if not loggerName in loggerInitialized: - syslogHandler = logging.handlers.SysLogHandler(address=(self._syslogDestinationHost, int(self._syslogDestinationPort))) + if loggerName not in loggerInitialized: + syslogHandler = logging.handlers.SysLogHandler( + address=(self._syslogDestinationHost, int(self._syslogDestinationPort))) self._l.addHandler(syslogHandler) loggerInitialized[loggerName] = True @@ -34,6 +41,7 @@ def flush(self, q): for x in q: self._l.info(x['_raw'].rstrip()) + def load(): """Returns an instance of the plugin""" return SyslogOutOutputPlugin diff --git a/splunk_eventgen/lib/plugins/output/tcpout.py b/splunk_eventgen/lib/plugins/output/tcpout.py index 3432d4bd..4658a00f 100644 --- a/splunk_eventgen/lib/plugins/output/tcpout.py +++ b/splunk_eventgen/lib/plugins/output/tcpout.py @@ -1,7 +1,10 @@ from __future__ import division -from outputplugin import OutputPlugin + import logging +from outputplugin import OutputPlugin + + class TcpOutputPlugin(OutputPlugin): useOutputQueue = False name = 'tcpout' @@ -10,13 +13,14 @@ class TcpOutputPlugin(OutputPlugin): def __init__(self, sample, output_counter=None): OutputPlugin.__init__(self, sample, output_counter) - self._tcpDestinationHost = sample.tcpDestinationHost if hasattr(sample,'tcpDestinationHost') and sample.tcpDestinationHost else '127.0.0.1' - self._tcpDestinationPort = sample.tcpDestinationPort if hasattr(sample,'tcpDestinationPort') and sample.tcpDestinationPort else '3333' + self._tcpDestinationHost = sample.tcpDestinationHost if hasattr( + sample, 'tcpDestinationHost') and sample.tcpDestinationHost else '127.0.0.1' + self._tcpDestinationPort = sample.tcpDestinationPort if hasattr( + sample, 'tcpDestinationPort') and sample.tcpDestinationPort else '3333' import socket # Import socket module self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # Bind to the port def flush(self, q): self.s.connect((self._tcpDestinationHost, int(self._tcpDestinationPort))) self.logger.info("Socket connected to {0}:{1}".format(self._tcpDestinationHost, self._tcpDestinationPort)) @@ -27,6 +31,7 @@ def flush(self, q): def _setup_logging(self): self.logger = logging.getLogger('eventgen') + def load(): """Returns an instance of the plugin""" - return TcpOutputPlugin \ No newline at end of file + return TcpOutputPlugin diff --git a/splunk_eventgen/lib/plugins/output/udpout.py b/splunk_eventgen/lib/plugins/output/udpout.py index 43477d0f..30e74324 100644 --- a/splunk_eventgen/lib/plugins/output/udpout.py +++ b/splunk_eventgen/lib/plugins/output/udpout.py @@ -1,7 +1,10 @@ from __future__ import division -from outputplugin import OutputPlugin + import logging +from outputplugin import OutputPlugin + + class UdpOutputPlugin(OutputPlugin): useOutputQueue = False name = 'udpout' @@ -10,8 +13,10 @@ class UdpOutputPlugin(OutputPlugin): def __init__(self, sample, output_counter=None): OutputPlugin.__init__(self, sample, output_counter) - self._udpDestinationHost = sample.udpDestinationHost if hasattr(sample,'udpDestinationHost') and sample.udpDestinationHost else '127.0.0.1' - self._udpDestinationPort = sample.udpDestinationPort if hasattr(sample,'udpDestinationPort') and sample.udpDestinationPort else '3333' + self._udpDestinationHost = sample.udpDestinationHost if hasattr( + sample, 'udpDestinationHost') and sample.udpDestinationHost else '127.0.0.1' + self._udpDestinationPort = sample.udpDestinationPort if hasattr( + sample, 'udpDestinationPort') and sample.udpDestinationPort else '3333' import socket # Import socket module self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -25,6 +30,7 @@ def flush(self, q): def _setup_logging(self): self.logger = logging.getLogger('eventgen') + def load(): """Returns an instance of the plugin""" - return UdpOutputPlugin \ No newline at end of file + return UdpOutputPlugin diff --git a/splunk_eventgen/lib/plugins/rater/config.py b/splunk_eventgen/lib/plugins/rater/config.py index d15136bd..d49581de 100644 --- a/splunk_eventgen/lib/plugins/rater/config.py +++ b/splunk_eventgen/lib/plugins/rater/config.py @@ -1,7 +1,8 @@ from __future__ import division + +import datetime import logging import logging.handlers -import datetime import random import os @@ -21,7 +22,7 @@ def __init__(self, sample): def __str__(self): """Only used for debugging, outputs a pretty printed representation of this output""" # Eliminate recursive going back to parent - temp = dict([ (key, value) for (key, value) in self.__dict__.items() if key != '_c']) + # temp = dict([(key, value) for (key, value) in self.__dict__.items() if key != '_c']) # return pprint.pformat(temp) return "" @@ -50,21 +51,21 @@ def rate(self): self.logger.error('No sample found for default generator, cannot generate events') self._sample.count = len(self._sample.sampleDict) self._generatorWorkers = int(self._generatorWorkers) - count = self._sample.count/self._generatorWorkers + count = self._sample.count / self._generatorWorkers # 5/8/12 CS We've requested not the whole file, so we should adjust count based on # hourOfDay, dayOfWeek and randomizeCount configs rateFactor = 1.0 if self._sample.randomizeCount: try: - self.logger.debug("randomizeCount for sample '%s' in app '%s' is %s" - % (self._sample.name, self._sample.app, self._sample.randomizeCount)) + self.logger.debug("randomizeCount for sample '%s' in app '%s' is %s" % + (self._sample.name, self._sample.app, self._sample.randomizeCount)) # If we say we're going to be 20% variable, then that means we # can be .1% high or .1% low. Math below does that. randBound = round(self._sample.randomizeCount * 1000, 0) rand = random.randint(0, randBound) - randFactor = 1+((-((randBound / 2) - rand)) / 1000) - self.logger.debug("randFactor for sample '%s' in app '%s' is %s" \ - % (self._sample.name, self._sample.app, randFactor)) + randFactor = 1 + ((-((randBound / 2) - rand)) / 1000) + self.logger.debug( + "randFactor for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, randFactor)) rateFactor *= randFactor except: import traceback @@ -73,12 +74,14 @@ def rate(self): if type(self._sample.hourOfDayRate) == dict: try: rate = self._sample.hourOfDayRate[str(self._sample.now().hour)] - self.logger.debug("hourOfDayRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) + self.logger.debug( + "hourOfDayRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) rateFactor *= rate except KeyError: import traceback stack = traceback.format_exc() - self.logger.error("Hour of day rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) + self.logger.error( + "Hour of day rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) if type(self._sample.dayOfWeekRate) == dict: try: weekday = datetime.date.weekday(self._sample.now()) @@ -87,43 +90,52 @@ def rate(self): else: weekday += 1 rate = self._sample.dayOfWeekRate[str(weekday)] - self.logger.debugv("dayOfWeekRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) + self.logger.debug( + "dayOfWeekRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) rateFactor *= rate except KeyError: import traceback - stack = traceback.format_exc() - self.logger.error("Hour of day rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) + stack = traceback.format_exc() + self.logger.error( + "Hour of day rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) if type(self._sample.minuteOfHourRate) == dict: try: rate = self._sample.minuteOfHourRate[str(self._sample.now().minute)] - self.logger.debugv("minuteOfHourRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) + self.logger.debug( + "minuteOfHourRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) rateFactor *= rate except KeyError: import traceback - stack = traceback.format_exc() - self.logger.error("Minute of hour rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) + stack = traceback.format_exc() + self.logger.error( + "Minute of hour rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) if type(self._sample.dayOfMonthRate) == dict: try: rate = self._sample.dayOfMonthRate[str(self._sample.now().day)] - self.logger.debugv("dayOfMonthRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) + self.logger.debug( + "dayOfMonthRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) rateFactor *= rate except KeyError: import traceback - stack = traceback.format_exc() - self.logger.error("Day of Month rate for sample '%s' failed. Stacktrace %s" % (self._sample.name, stack)) + stack = traceback.format_exc() + self.logger.error( + "Day of Month rate for sample '%s' failed. Stacktrace %s" % (self._sample.name, stack)) if type(self._sample.monthOfYearRate) == dict: try: rate = self._sample.monthOfYearRate[str(self._sample.now().month)] - self.logger.debugv("monthOfYearRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) + self.logger.debug( + "monthOfYearRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) rateFactor *= rate except KeyError: import traceback - stack = traceback.format_exc() - self.logger.error("Month Of Year rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) + stack = traceback.format_exc() + self.logger.error( + "Month Of Year rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) ret = int(round(count * rateFactor, 0)) if rateFactor != 1.0: self.logger.debug("Original count: %s Rated count: %s Rate factor: %s" % (count, ret, rateFactor)) return ret + def load(): return ConfigRater diff --git a/splunk_eventgen/lib/plugins/rater/perdayvolume.py b/splunk_eventgen/lib/plugins/rater/perdayvolume.py index cfdf8746..3c8d217f 100644 --- a/splunk_eventgen/lib/plugins/rater/perdayvolume.py +++ b/splunk_eventgen/lib/plugins/rater/perdayvolume.py @@ -1,7 +1,8 @@ from __future__ import division -from config import ConfigRater + import datetime import random +from config import ConfigRater class PerDayVolume(ConfigRater): @@ -16,7 +17,7 @@ def __init__(self, sample): self._generatorWorkers = self._sample.config.generatorWorkers def rate(self): - perdayvolume = float(self._sample.perDayVolume)/self._generatorWorkers + perdayvolume = float(self._sample.perDayVolume) / self._generatorWorkers # Convert perdayvolume to bytes from GB perdayvolume = perdayvolume * 1024 * 1024 * 1024 interval = self._sample.interval @@ -28,21 +29,20 @@ def rate(self): perintervalvolume = (perdayvolume / intervalsperday) count = self._sample.count - # 5/8/12 CS We've requested not the whole file, so we should adjust count based on # hourOfDay, dayOfWeek and randomizeCount configs rateFactor = 1.0 - if self._sample.randomizeCount != 0 and self._sample.randomizeCount != None: + if self._sample.randomizeCount != 0 and self._sample.randomizeCount is not None: try: - self.logger.debugv("randomizeCount for sample '%s' in app '%s' is %s" \ - % (self._sample.name, self._sample.app, self._sample.randomizeCount)) + self.logger.debugv("randomizeCount for sample '%s' in app '%s' is %s" % + (self._sample.name, self._sample.app, self._sample.randomizeCount)) # If we say we're going to be 20% variable, then that means we # can be .1% high or .1% low. Math below does that. randBound = round(self._sample.randomizeCount * 1000, 0) rand = random.randint(0, randBound) - randFactor = 1+((-((randBound / 2) - rand)) / 1000) - self.logger.debug("randFactor for sample '%s' in app '%s' is %s" \ - % (self._sample.name, self._sample.app, randFactor)) + randFactor = 1 + ((-((randBound / 2) - rand)) / 1000) + self.logger.debug( + "randFactor for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, randFactor)) rateFactor *= randFactor except: import traceback @@ -51,12 +51,14 @@ def rate(self): if type(self._sample.hourOfDayRate) == dict: try: rate = self._sample.hourOfDayRate[str(self._sample.now().hour)] - self.logger.debugv("hourOfDayRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) + self.logger.debugv( + "hourOfDayRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) rateFactor *= rate except KeyError: import traceback stack = traceback.format_exc() - self.logger.error("Hour of day rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) + self.logger.error( + "Hour of day rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) if type(self._sample.dayOfWeekRate) == dict: try: weekday = datetime.date.weekday(self._sample.now()) @@ -65,46 +67,55 @@ def rate(self): else: weekday += 1 rate = self._sample.dayOfWeekRate[str(weekday)] - self.logger.debugv("dayOfWeekRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) + self.logger.debugv( + "dayOfWeekRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) rateFactor *= rate except KeyError: import traceback stack = traceback.format_exc() - self.logger.error("Hour of day rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) + self.logger.error( + "Hour of day rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) if type(self._sample.minuteOfHourRate) == dict: try: rate = self._sample.minuteOfHourRate[str(self._sample.now().minute)] - self.logger.debugv("minuteOfHourRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) + self.logger.debugv( + "minuteOfHourRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) rateFactor *= rate except KeyError: import traceback stack = traceback.format_exc() - self.logger.error("Minute of hour rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) + self.logger.error( + "Minute of hour rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) if type(self._sample.dayOfMonthRate) == dict: try: rate = self._sample.dayOfMonthRate[str(self._sample.now().day)] - self.logger.debugv("dayOfMonthRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) + self.logger.debugv( + "dayOfMonthRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) rateFactor *= rate except KeyError: import traceback stack = traceback.format_exc() - self.logger.error("Day of Month rate for sample '%s' failed. Stacktrace %s" % (self._sample.name, stack)) + self.logger.error( + "Day of Month rate for sample '%s' failed. Stacktrace %s" % (self._sample.name, stack)) if type(self._sample.monthOfYearRate) == dict: try: rate = self._sample.monthOfYearRate[str(self._sample.now().month)] - self.logger.debugv("monthOfYearRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) + self.logger.debugv( + "monthOfYearRate for sample '%s' in app '%s' is %s" % (self._sample.name, self._sample.app, rate)) rateFactor *= rate except KeyError: import traceback stack = traceback.format_exc() - self.logger.error("Month Of Year rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) + self.logger.error( + "Month Of Year rate failed for sample '%s'. Stacktrace %s" % (self._sample.name, stack)) self.logger.debug("Size per interval: %s, rate factor to adjust by: %s" % (perintervalvolume, rateFactor)) ret = int(round(perintervalvolume * rateFactor, 0)) if rateFactor != 1.0: self.logger.debug("Original count: %s Rated count: %s Rate factor: %s" % (count, ret, rateFactor)) - self.logger.debug("Finished rating, interval: {0}s, generation rate: {1} MB/interval".format(interval, round((ret / 1024 / 1024), 4))) + self.logger.debug("Finished rating, interval: {0}s, generation rate: {1} MB/interval".format( + interval, round((ret / 1024 / 1024), 4))) return ret def load(): - return PerDayVolume \ No newline at end of file + return PerDayVolume diff --git a/splunk_eventgen/lib/timeparser.py b/splunk_eventgen/lib/timeparser.py index 4efeab36..020818b8 100644 --- a/splunk_eventgen/lib/timeparser.py +++ b/splunk_eventgen/lib/timeparser.py @@ -1,86 +1,89 @@ import datetime -import re -import math import logging - +import math +import os +import re # Hack to allow distributing python modules since Splunk doesn't have setuptools # We create the egg outside of Splunk (with a copy of python2.7 and using Python only modules # To avoid being platform specific) and then append the egg path and import the module # If we get a lot of these we'll move the eggs from bin to lib # # python-dateutil acquired from http://labix.org/python-dateutil. BSD Licensed -import sys, os +import sys + path_prepend = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'lib') sys.path.append(path_prepend + '/python_dateutil-1.4.1-py2.7.egg') -import dateutil.parser as dateutil_parser +import dateutil.parser as dateutil_parser # noqa isort:skip # If we're inside eventgen, we'll have a global logger, if not set one up logging.getLogger('eventgen') + # 5-5-2012 CS Replacing TimeParser with our own code to remove Splunk dependency -# Based off spec for relative time identifiers at http://docs.splunk.com/Documentation/Splunk/latest/SearchReference/SearchTimeModifiers#How_to_specify_relative_time_modifiers +# Based off spec for relative time identifiers at http://docs.splunk.com/Documentation/Splunk/latest/SearchReference/SearchTimeModifiers#How_to_specify_relative_time_modifiers # noqa # If we're not relative, we'll try to parse it as an ISO compliant time def timeParser(ts='now', timezone=datetime.timedelta(days=1), now=None, utcnow=None): if ts == 'now': if timezone.days > 0: - if now == None: + if now is None: return datetime.datetime.now() else: return now() else: - if utcnow == None: + if utcnow is None: return datetime.datetime.now() else: return utcnow() + timezone else: if ts[:1] == '+' or ts[:1] == '-': if timezone.days > 0: - if now == None: + if now is None: ret = datetime.datetime.now() else: ret = now() else: - if utcnow == None: + if utcnow is None: ret = datetime.datetime.utcnow() + timezone else: ret = utcnow() + timezone - - unitsre = "(seconds|second|secs|sec|minutes|minute|min|hours|hour|hrs|hr|days|day|weeks|week|w[0-6]|months|month|mon|quarters|quarter|qtrs|qtr|years|year|yrs|yr|s|h|m|d|w|y|w|q)" - reltimere = "(?i)(?P[+-]*)(?P\d{1,})(?P"+unitsre+"{1})(([\@](?P"+unitsre+"{1})((?P[+-])(?P\d+)(?P"+unitsre+"{1}))*)*)" - + + unitsre = "(seconds|second|secs|sec|minutes|minute|min|hours|hour|hrs|hr|days|day|weeks|week|w[0-6]|" + \ + "months|month|mon|quarters|quarter|qtrs|qtr|years|year|yrs|yr|s|h|m|d|w|y|w|q)" + reltimere = "(?i)(?P[+-]*)(?P\d{1,})(?P" + unitsre + "{1})(([\@](?P" + \ + unitsre + "{1})((?P[+-])(?P\d+)(?P" + unitsre + \ + "{1}))*)*)" + results = re.match(reltimere, ts) resultsdict = results.groupdict() - + # Handle first part of the time string - if resultsdict['plusminus'] != None and resultsdict['num'] != None \ - and resultsdict['unit'] != None: + if resultsdict['plusminus'] is not None and resultsdict['num'] is not None \ + and resultsdict['unit'] is not None: ret = timeParserTimeMath(resultsdict['plusminus'], resultsdict['num'], resultsdict['unit'], ret) - + # Now handle snap-to - if resultsdict['snapunit'] != None: + if resultsdict['snapunit'] is not None: if resultsdict['snapunit'] in ('s', 'sec', 'secs', 'second', 'seconds'): - ret = datetime.datetime(ret.year, ret.month, ret.day, ret.hour, \ - ret.minute, ret.second, 0) + ret = datetime.datetime(ret.year, ret.month, ret.day, ret.hour, ret.minute, ret.second, 0) elif resultsdict['snapunit'] in ('m', 'min', 'minute', 'minutes'): - ret = datetime.datetime(ret.year, ret.month, ret.day, ret.hour, \ - ret.minute, 0, 0) + ret = datetime.datetime(ret.year, ret.month, ret.day, ret.hour, ret.minute, 0, 0) elif resultsdict['snapunit'] in ('h', 'hr', 'hrs', 'hour', 'hours'): ret = datetime.datetime(ret.year, ret.month, ret.day, ret.hour, 0, 0, 0) elif resultsdict['snapunit'] in ('d', 'day', 'days'): ret = datetime.datetime(ret.year, ret.month, ret.day, 0, 0, 0, 0) - elif re.match('w[0-6]', resultsdict['snapunit']) != None or \ + elif re.match('w[0-6]', resultsdict['snapunit']) is not None or \ resultsdict['snapunit'] in ('w', 'week', 'weeks'): if resultsdict['snapunit'] in ('w', 'week', 'weeks'): resultsdict['snapunit'] = 'w0' weekdaynum = int(resultsdict['snapunit'][1:2]) - + # Convert python's weekdays to Splunk's retweekday = datetime.date.weekday(ret) if retweekday == 6: retweekday = 0 else: retweekday += 1 - + if weekdaynum <= retweekday: ret = ret + datetime.timedelta(days=(weekdaynum - retweekday)) ret = datetime.datetime(ret.year, ret.month, ret.day, 0, 0, 0, 0) @@ -96,23 +99,24 @@ def timeParser(ts='now', timezone=datetime.timedelta(days=1), now=None, utcnow=N ret = datetime.datetime(ret.year, int(math.floor(ret.month / 3.3 + 1) * 3), 1, 0, 0, 0, 0) elif resultsdict['snapunit'] in ('y', 'yr', 'yrs', 'year', 'years'): ret = datetime.datetime(ret.year, 1, 1, 0, 0, 0, 0) - - if resultsdict['snapplusminus'] != None and resultsdict['snaprelnum'] != None \ - and resultsdict['snaprelunit'] != None: - ret = timeParserTimeMath(resultsdict['snapplusminus'], resultsdict['snaprelnum'], - resultsdict['snaprelunit'], ret) + + if resultsdict['snapplusminus'] is not None and resultsdict['snaprelnum'] is not None \ + and resultsdict['snaprelunit'] is not None: + ret = timeParserTimeMath(resultsdict['snapplusminus'], resultsdict['snaprelnum'], + resultsdict['snaprelunit'], ret) return ret - + else: - raise ValueError('Cannot parse relative time string for %s' %(ts)) + raise ValueError('Cannot parse relative time string for %s' % (ts)) else: - # The spec says we must be a ISO8601 time. This parser should be able to handle + # The spec says we must be a ISO8601 time. This parser should be able to handle # more date formats though, so we can be liberal in what we accept return dateutil_parser.parse(ts) - #except ValueError: + # except ValueError: # raise ValueError("Cannot parse date/time for %s" % (ts)) + def timeParserTimeMath(plusminus, num, unit, ret): try: num = int(num) @@ -126,59 +130,59 @@ def timeParserTimeMath(plusminus, num, unit, ret): elif unit in ('d', 'day', 'days'): td = datetime.timedelta(days=int(num)) elif unit in ('w', 'week', 'weeks'): - td = datetime.timedelta(days=(int(num)*7)) - elif re.match('w[0-6]', unit) != None: - logger.error('Day of week is only available in snap-to. Time string: %s' % (ts)) + td = datetime.timedelta(days=(int(num) * 7)) + elif re.match('w[0-6]', unit) is not None: + logging.error('Day of week is only available in snap-to. Time string: %s' % td) return False # Normalize out all year/quarter/months to months and do the math on that - elif unit in ('mon', 'month', 'months') or \ - unit in ('q', 'qtr', 'qtrs', 'quarter', 'quarters') or \ - unit in ('y', 'yr', 'yrs', 'year', 'years'): + elif unit in ('mon', 'month', 'months') or unit in ('q', 'qtr', 'qtrs', 'quarter', 'quarters') or \ + unit in ('y', 'yr', 'yrs', 'year', 'years'): if unit in ('q', 'qtr', 'qtrs', 'quarter', 'quarters'): num *= 3 elif unit in ('y', 'yr', 'yrs', 'year', 'years'): num *= 12 - + monthnum = int(num) * -1 if plusminus == '-' else int(num) if abs(monthnum) / 12 > 0: - yearnum = int(math.floor(abs(monthnum)/12) * -1 if plusminus == '-' else int(math.floor(abs(monthnum)/12))) - monthnum = int((abs(monthnum) % 12) * -1 if plusminus == '-' else int((abs(monthnum)%12))) - ret = datetime.datetime(ret.year + yearnum, ret.month + monthnum, ret.day, ret.hour, - ret.minute, ret.second, ret.microsecond) + yearnum = int( + math.floor(abs(monthnum) / 12) * -1 if plusminus == '-' else int(math.floor(abs(monthnum) / 12))) + monthnum = int((abs(monthnum) % 12) * -1 if plusminus == '-' else int((abs(monthnum) % 12))) + ret = datetime.datetime(ret.year + yearnum, ret.month + monthnum, ret.day, ret.hour, ret.minute, + ret.second, ret.microsecond) elif monthnum > 0: if ret.month + monthnum > 12: - ret = datetime.datetime(ret.year+1, ((ret.month+monthnum)%12), - ret.day, ret.hour, ret.minute, ret.second, ret.microsecond) + ret = datetime.datetime(ret.year + 1, ((ret.month + monthnum) % 12), ret.day, ret.hour, ret.minute, + ret.second, ret.microsecond) else: - ret = datetime.datetime(ret.year, ret.month+monthnum, ret.day, - ret.hour, ret.minute, ret.second, ret.microsecond) + ret = datetime.datetime(ret.year, ret.month + monthnum, ret.day, ret.hour, ret.minute, ret.second, + ret.microsecond) elif monthnum <= 0: if ret.month + monthnum <= 0: - ret = datetime.datetime(ret.year-1, (12-abs(ret.month+monthnum)), - ret.day, ret.hour, ret.minute, ret.second, ret.microsecond) + ret = datetime.datetime(ret.year - 1, (12 - abs(ret.month + monthnum)), ret.day, ret.hour, + ret.minute, ret.second, ret.microsecond) else: - ret = datetime.datetime(ret.year, ret.month+monthnum, ret.day, - ret.hour, ret.minute, ret.second, ret.microsecond) + ret = datetime.datetime(ret.year, ret.month + monthnum, ret.day, ret.hour, ret.minute, ret.second, + ret.microsecond) except ValueError: - logger.error('Cannot parse relative time string') + logging.error('Cannot parse relative time string') import traceback - stack = traceback.format_exc() - logger.debug('%s', stack) + stack = traceback.format_exc() + logging.debug('%s', stack) return False - - if td != None: + + if td is not None: if plusminus == '-': td = td * -1 ret = ret + td - + # Always chop microseconds to maintain compatibility with Splunk's parser ret = datetime.datetime(ret.year, ret.month, ret.day, ret.hour, ret.minute, ret.second) - + return ret - -## Converts Time Delta object to number of seconds in delta + + +# Converts Time Delta object to number of seconds in delta def timeDelta2secs(timeDiff): deltaSecs = (timeDiff.microseconds + (timeDiff.seconds + timeDiff.days * 24 * 3600) * 10**6) / 10**6 return int(deltaSecs) - \ No newline at end of file diff --git a/splunk_eventgen/logger/logger_config.py b/splunk_eventgen/logger/logger_config.py index d2d5b46f..444ef5f9 100644 --- a/splunk_eventgen/logger/logger_config.py +++ b/splunk_eventgen/logger/logger_config.py @@ -2,26 +2,15 @@ 'version': 1, 'formatters': { 'detailed': { - 'class': 'logging.Formatter', - 'format': '%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s' - } - }, + 'class': 'logging.Formatter', 'format': + '%(asctime)s %(name)-15s %(levelname)-8s %(processName)-10s %(message)s'}}, 'handlers': { 'console': { 'class': 'logging.StreamHandler', 'level': 'INFO', - 'formatter': 'detailed', - }, - 'main': { - 'class': 'logging.FileHandler', - 'filename': 'eventgen-controller-main.log', - 'mode': 'w', - 'formatter': 'detailed', - } - }, - 'root': { - 'level': 'DEBUG', - 'handlers': ['console', 'main'] - }, -} - + 'formatter': 'detailed', }, 'main': { + 'class': 'logging.FileHandler', + 'filename': 'eventgen-controller-main.log', + 'mode': 'w', + 'formatter': 'detailed', }}, + 'root': {'level': 'DEBUG', 'handlers': ['console', 'main']}, } diff --git a/splunk_eventgen/logger/requests_futures/__init__.py b/splunk_eventgen/logger/requests_futures/__init__.py index 9ac9cd31..ac0c4f3e 100755 --- a/splunk_eventgen/logger/requests_futures/__init__.py +++ b/splunk_eventgen/logger/requests_futures/__init__.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- # Requests Futures - """ async requests HTTP library ~~~~~~~~~~~~~~~~~~~~~ @@ -22,8 +21,10 @@ try: # Python 2.7+ from logging import NullHandler except ImportError: + class NullHandler(logging.Handler): def emit(self, record): pass + logging.getLogger(__name__).addHandler(NullHandler()) diff --git a/splunk_eventgen/logger/requests_futures/sessions.py b/splunk_eventgen/logger/requests_futures/sessions.py index 7fba4226..643f4e1d 100755 --- a/splunk_eventgen/logger/requests_futures/sessions.py +++ b/splunk_eventgen/logger/requests_futures/sessions.py @@ -19,9 +19,9 @@ print(response.content) """ -from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor +from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor from functools import partial -from pickle import dumps, PickleError +from pickle import PickleError, dumps from requests import Session from requests.adapters import DEFAULT_POOLSIZE, HTTPAdapter @@ -38,9 +38,7 @@ def wrap(self, sup, background_callback, *args_, **kwargs_): class FuturesSession(Session): - - def __init__(self, executor=None, max_workers=2, session=None, *args, - **kwargs): + def __init__(self, executor=None, max_workers=2, session=None, *args, **kwargs): """Creates a FuturesSession Notes @@ -56,8 +54,7 @@ def __init__(self, executor=None, max_workers=2, session=None, *args, executor = ThreadPoolExecutor(max_workers=max_workers) # set connection pool size equal to max_workers if needed if max_workers > DEFAULT_POOLSIZE: - adapter_kwargs = dict(pool_connections=max_workers, - pool_maxsize=max_workers) + adapter_kwargs = dict(pool_connections=max_workers, pool_maxsize=max_workers) self.mount('https://', HTTPAdapter(**adapter_kwargs)) self.mount('http://', HTTPAdapter(**adapter_kwargs)) diff --git a/splunk_eventgen/splunk_app/bin/modinput_eventgen.py b/splunk_eventgen/splunk_app/bin/modinput_eventgen.py index db1e6115..15463bc5 100644 --- a/splunk_eventgen/splunk_app/bin/modinput_eventgen.py +++ b/splunk_eventgen/splunk_app/bin/modinput_eventgen.py @@ -1,25 +1,26 @@ #!/usr/bin/env python # encoding: utf-8 -import sys -import logging import argparse +import logging import signal +import sys +from modinput import ModularInput +from modinput.fields import VerbosityField # Set path so libraries will load from splunk.clilib.bundle_paths import make_splunkhome_path -sys.path.insert(0, make_splunkhome_path(['etc', 'apps', 'SA-Eventgen', 'lib'])) -sys.path.insert(0, make_splunkhome_path(['etc', 'apps', 'SA-Eventgen', 'lib', 'splunk_eventgen', 'lib'])) - -from modinput.fields import BooleanField, Field, VerbosityField -from xmloutput import setupLogger, XMLOutputManager -from modinput import ModularInput from splunk_eventgen import eventgen_core from splunk_eventgen.lib import eventgenconfig +from xmloutput import XMLOutputManager, setupLogger + +sys.path.insert(0, make_splunkhome_path(['etc', 'apps', 'SA-Eventgen', 'lib'])) +sys.path.insert(0, make_splunkhome_path(['etc', 'apps', 'SA-Eventgen', 'lib', 'splunk_eventgen', 'lib'])) # Initialize logging logger = setupLogger(logger=None, log_format='%(asctime)s %(levelname)s [Eventgen] %(message)s', level=logging.DEBUG, log_name="modinput_eventgen.log", logger_name="eventgen_app") + class SimpleNamespace(dict): """dot.notation access to dictionary attributes""" __getattr__ = dict.get @@ -29,12 +30,8 @@ class SimpleNamespace(dict): class Eventgen(ModularInput): scheme_args = { - 'title': "SA-Eventgen", - 'description': "This modular input generates data for Splunk.", - 'use_external_validation': "true", - 'streaming_mode': "xml", - 'use_single_instance': "False" - } + 'title': "SA-Eventgen", 'description': "This modular input generates data for Splunk.", + 'use_external_validation': "true", 'streaming_mode': "xml", 'use_single_instance': "False"} def __init__(self): logger.debug("Setting up SA-Eventgen Modular Input") @@ -42,9 +39,8 @@ def __init__(self): self.args = [ VerbosityField("verbosity", "Verbosity", - "Logging Level (DEBUG(10), INFO(20), WARN(30), ERROR(40), CRITICAL(50))", - required_on_create=True, required_on_edit=True) - ] + "Logging Level (DEBUG(10), INFO(20), WARN(30), ERROR(40), CRITICAL(50))", + required_on_create=True, required_on_edit=True)] ModularInput.__init__(self, self.scheme_args, self.args) def create_args(self): @@ -138,14 +134,17 @@ def run(self, stanza, input_config, **kwargs): logger.error("Main code exit, Exception caught: %s" % e) raise e + def handler(signum, frame): logger.info("Eventgen Modinput takes signal {0}. Exiting".format(signum)) sys.exit(0) + def handle_signal(): if not sys.platform.startswith('win') and sys.platform != "cygwin": signal.signal(signal.SIGPIPE, handler) + if __name__ == '__main__': handle_signal() worker = Eventgen() diff --git a/splunk_eventgen/splunk_app/lib/modinput/__init__.py b/splunk_eventgen/splunk_app/lib/modinput/__init__.py index 11542901..44c4bcc3 100644 --- a/splunk_eventgen/splunk_app/lib/modinput/__init__.py +++ b/splunk_eventgen/splunk_app/lib/modinput/__init__.py @@ -10,14 +10,18 @@ import sys import time import xml.dom -from xml.dom.minidom import Document import xml.sax.saxutils +from xml.dom.minidom import Document import splunk import splunk.clilib import splunk.version -from splunk.models.app import App from splunk.clilib.bundle_paths import get_slaveapps_base_path +from splunk.models.app import App +from xmloutput import setupLogger + +from .fields import (BooleanField, Field, FieldValidationException, IntervalField) + try: from splunk.clilib.bundle_paths import make_splunkhome_path except ImportError: @@ -28,27 +32,13 @@ else: sys.path.append(make_splunkhome_path(["etc", "apps", "@appname@", "lib"])) -from .fields import BooleanField -from .fields import DurationField -from .fields import Field -from .fields import FieldValidationException -from .fields import FloatField -from .fields import IntegerField -from .fields import IntervalField -from .fields import ListField -from .fields import RangeField -from .fields import RegexField -from .fields import SeverityField - -from xmloutput import setupLogger, XMLOutputManager - # Define logger using the name of the script here, versus in the modular_input class. -#logger = log.setup_logger(name='python_modular_input', level=logging.INFO) -logger = setupLogger(logger=None, log_format='%(asctime)s %(levelname)s [ModularInput] %(message)s', level=logging.INFO, log_name="python_modular_input.log", logger_name="modinput") +# logger = log.setup_logger(name='python_modular_input', level=logging.INFO) +logger = setupLogger(logger=None, log_format='%(asctime)s %(levelname)s [ModularInput] %(message)s', level=logging.INFO, + log_name="python_modular_input.log", logger_name="modinput") class ModularInputConfig(object): - def __init__(self, server_host, server_uri, session_key, checkpoint_dir, configuration): self.server_host = server_host self.server_uri = server_uri @@ -135,14 +125,13 @@ class ModularInput(object): # These arguments cover the standard fields that are always supplied standard_args = [ - BooleanField("disabled", "Disabled", "Whether the modular input is disabled or not"), - Field("host", "Host", "The host that is running the input"), - Field("index", "Index", "The index that data should be sent to"), - IntervalField("interval", "Interval", "The interval the script will be run on"), - Field("name", "Stanza name", "The name of the stanza for this modular input"), - Field("source", "Source", "The source for events created by this modular input"), - Field("sourcetype", "Stanza name", "The name of the stanza for this modular input") - ] + BooleanField("disabled", "Disabled", "Whether the modular input is disabled or not"), + Field("host", "Host", "The host that is running the input"), + Field("index", "Index", "The index that data should be sent to"), + IntervalField("interval", "Interval", "The interval the script will be run on"), + Field("name", "Stanza name", "The name of the stanza for this modular input"), + Field("source", "Source", "The source for events created by this modular input"), + Field("sourcetype", "Stanza name", "The name of the stanza for this modular input")] checkpoint_dir = None @@ -401,7 +390,8 @@ def add_xml_args(self, doc, element_args): def do_validation(self, in_stream=sys.stdin): """ - Get the validation data from standard input and attempt to validate it. Returns true if the arguments validated, false otherwise. + Get the validation data from standard input and attempt to validate it. Returns true if the arguments validated, + false otherwise. Arguments: in_stream -- The stream to get the input from (defaults to standard input) @@ -421,7 +411,7 @@ def validate(self, arguments): Validate the argument dictionary where each key is a stanza. Arguments: - arguments -- The arguments as an dictionary where the key is the stanza and the value is a dictionary of the values. + arguments -- a dictionary where the key is the stanza and the value is a dictionary of the values. """ # Check each stanza @@ -541,23 +531,19 @@ def needs_another_run(cls, checkpoint_dir, stanza, interval, cur_time=None): try: last_ran = cls.last_ran(checkpoint_dir, stanza) - return cls.is_expired(last_ran, interval, cur_time) - - except IOError as e: + except IOError: # The file likely doesn't exist logger.exception("The checkpoint file likely doesn't exist") return True - except ValueError as e: + except ValueError: # The file could not be loaded logger.exception("The checkpoint file could not be loaded") return True except Exception as e: - #Catch all that enforces an extra run + # Catch all that enforces an extra run logger.exception("Unexpected exception caught, enforcing extra run, exception info: " + str(e)) return True - # Default return value - return True @classmethod def time_to_next_run(cls, checkpoint_dir, stanza, duration): @@ -582,18 +568,17 @@ def time_to_next_run(cls, checkpoint_dir, stanza, duration): return time_to_next except IOError: # The file likely doesn't exist - logger.warning("Could not read checkpoint file for last time run, likely does not exist, if this persists debug input immediately") + logger.warning("Could not read checkpoint file for last time run, likely does not exist, if this" + + "persists debug input immediately") return 1 except ValueError: # The file could not be loaded - logger.exception("Could not read checkpoint file for last time run, if this persists debug input immediately") + logger.exception( + "Could not read checkpoint file for last time run, if this persists debug input immediately") return 1 except Exception as e: logger.exception("Unexpected exception caught, enforcing extra run, exception info: " + str(e)) return 1 - # Default return value - logger.info("This really should be impossible, but whatevs if your input is breaking check the duration calculations") - return 1 @classmethod def save_checkpoint(cls, checkpoint_dir, stanza, last_run): @@ -663,7 +648,9 @@ def delete_checkpoint_data(self, filename, checkpoint_dir=None): os.unlink(os.path.join(checkpoint_dir, filename)) return True except IOError: - logger.exception('msg="IOError exception when deleting checkpoint data" checkpoint_dir="{}" filename="{}"'.format(checkpoint_dir, filename)) + logger.exception( + 'msg="IOError exception when deleting checkpoint data" checkpoint_dir="{}" filename="{}"'.format( + checkpoint_dir, filename)) return False def set_checkpoint_data(self, filename, data, checkpoint_dir=None): @@ -693,11 +680,17 @@ def set_checkpoint_data(self, filename, data, checkpoint_dir=None): json.dump(data, fp) success = True except IOError: - logger.exception('msg="IOError exception when saving checkpoint data" checkpoint_dir="{}" filename="{}"'.format(checkpoint_dir, filename)) + logger.exception( + 'msg="IOError exception when saving checkpoint data" checkpoint_dir="{}" filename="{}"'.format( + checkpoint_dir, filename)) except ValueError: - logger.exception('msg="ValueError when saving checkpoint data (perhaps invalid JSON)" checkpoint_dir="{}" filename="{}"'.format(checkpoint_dir, filename)) + logger.exception( + 'msg="ValueError when saving checkpoint data (perhaps invalid JSON)" checkpoint_dir="{}" filename="{}"'. + format(checkpoint_dir, filename)) except Exception: - logger.exception('msg="Unknown exception when saving checkpoint data" checkpoint_dir="{}" filename="{}"'.format(checkpoint_dir, filename)) + logger.exception( + 'msg="Unknown exception when saving checkpoint data" checkpoint_dir="{}" filename="{}"'.format( + checkpoint_dir, filename)) return success def get_checkpoint_data(self, filename, checkpoint_dir=None, raise_known_exceptions=False): @@ -727,11 +720,15 @@ def get_checkpoint_data(self, filename, checkpoint_dir=None, raise_known_excepti with open(checkpoint_path, 'r') as fp: data = json.load(fp) except (IOError, ValueError) as e: - logger.exception('msg="Exception when reading checkpoint data" checkpoint_dir="{}" filename="{}" exception="%s"'.format(checkpoint_dir, filename, e)) + logger.exception( + 'msg="Exception when reading checkpoint data" checkpoint_dir="{}" filename="{}" exception="%s"'.format( + checkpoint_dir, filename, e)) if raise_known_exceptions: raise except Exception: - logger.exception('msg="Unknown exception when reading checkpoint data" checkpoint_dir="{}" filename="{}"'.format(checkpoint_dir, filename)) + logger.exception( + 'msg="Unknown exception when reading checkpoint data" checkpoint_dir="{}" filename="{}"'.format( + checkpoint_dir, filename)) raise return data @@ -741,7 +738,8 @@ def do_run(self, in_stream=sys.stdin, log_exception_and_continue=False): Read the config from standard input and return the configuration. in_stream -- The stream to get the input from (defaults to standard input) - log_exception_and_continue -- If true, exceptions will not be thrown for invalid configurations and instead the stanza will be skipped. + log_exception_and_continue -- If true, exceptions will not be thrown for invalid configurations and instead the + stanza will be skipped. """ # Run the modular import @@ -779,14 +777,12 @@ def do_run(self, in_stream=sys.stdin, log_exception_and_continue=False): # Note: The "duration" parameter emulates the behavior of the "interval" # parameter available on Splunk 6.x and higher, and is mainly used by the # VMWare application. - - # TODO: A run() method may pass results back for optional processing - results = None + # TODO: should we collect/process results from run()? if stanzas: if single_instance: # Run the input across all defined stanzas and exit. - results = self.run(stanzas, self._input_config) + self.run(stanzas, self._input_config) else: # Retrieve the single input stanza. stanza = stanzas[0] @@ -795,7 +791,8 @@ def do_run(self, in_stream=sys.stdin, log_exception_and_continue=False): except ValueError as e: # This should never happen unless the author of the modular input # fails to specify "duration" as an IntegerField. - logger.exception("Input stanza '%s' specified an invalid duration: %s" % (stanza.get('name', 'unknown'), str(e))) + logger.exception( + "Input stanza '%s' specified an invalid duration: %s" % (stanza.get('name', 'unknown'), str(e))) # Exit with non-zero exit code so services/admin/inputstatus correctly reflects script status. sys.exit(1) @@ -805,7 +802,7 @@ def do_run(self, in_stream=sys.stdin, log_exception_and_continue=False): # If there splunk 6.0 and interval field is defined, then ignore duration fields completely if stanza.get("interval", -1) >= 0 and splunk.version.__version__ >= '6.0': # Run the single stanza and exit. - results = self.run(stanza, self._input_config) + self.run(stanza, self._input_config) else: # Run duration field if duration > 0 and self.checkpoint_dir: @@ -819,13 +816,13 @@ def do_run(self, in_stream=sys.stdin, log_exception_and_continue=False): # use the name of the input itself, unhashed. Name collisions would # be a configuration error. self.save_checkpoint(self.checkpoint_dir, stanza_name, int(time.time())) - results = self.run(stanza, ) + self.run(stanza, self._input_config) # Results processing, if any, could occur here. time.sleep(ModularInput.time_to_next_run(self.checkpoint_dir, stanza_name, duration)) else: # Duration is not defined # Run the single stanza and exit for Splunk 5.x - results = self.run(stanza, self._input_config) + self.run(stanza, self._input_config) else: logger.info("No input stanzas defined") @@ -899,13 +896,11 @@ def _parse_args(self, argv): parser = argparse.ArgumentParser(description='Modular input parameters') - mode_args= parser.add_mutually_exclusive_group() + mode_args = parser.add_mutually_exclusive_group() debug_args = parser.add_argument_group() - debug_args.add_argument('--username', action="store", default=None, - help="Splunk username (%s)" % warning_text) - debug_args.add_argument('--password', action="store", default=None, - help="Splunk password (%s)" % warning_text) + debug_args.add_argument('--username', action="store", default=None, help="Splunk username (%s)" % warning_text) + debug_args.add_argument('--password', action="store", default=None, help="Splunk password (%s)" % warning_text) debug_args.add_argument('--infile', type=argparse.FileType(), default=None, help="Filename containing XML modular input configuration (%s)" % warning_text) @@ -936,7 +931,7 @@ def execute(self, in_stream=sys.stdin, out_stream=sys.stdout): logger.info("Modular input: validate arguments called") # Exit with a code of -1 if validation failed - if self.do_validation() == False: + if self.do_validation() is False: sys.exit(-1) else: @@ -959,7 +954,8 @@ def execute(self, in_stream=sys.stdin, out_stream=sys.stdout): try: self.do_run(args.infile, log_exception_and_continue=True) except IOError: - logger.exception("Modular input: modinput configuration could not be read from file %s.", args.infile.name) + logger.exception("Modular input: modinput configuration could not be read from file %s.", + args.infile.name) else: try: self.do_run(in_stream, log_exception_and_continue=True) @@ -1034,4 +1030,4 @@ def is_configured(self, app=None, assume_true_on_error=False): except splunk.RESTException: return assume_true_on_error else: - return assume_true_on_error \ No newline at end of file + return assume_true_on_error diff --git a/splunk_eventgen/splunk_app/lib/modinput/fields.py b/splunk_eventgen/splunk_app/lib/modinput/fields.py index 40d6b37b..681ae6d5 100644 --- a/splunk_eventgen/splunk_app/lib/modinput/fields.py +++ b/splunk_eventgen/splunk_app/lib/modinput/fields.py @@ -11,7 +11,8 @@ class FieldValidationException(Exception): class Field(object): """ - This is the base class that should be used to create field validators. Sub-class this and override to_python if you need custom validation. + This is the base class that should be used to create field validators. Sub-class this and override to_python if you + need custom validation. """ DATA_TYPE_STRING = 'string' @@ -32,7 +33,8 @@ def __init__(self, name, title, description, required_on_create=True, required_o Arguments: name -- Set the name of the field (e.g. "database_server") title -- Set the human readable title (e.g. "Database server") - description -- Set the human readable description of the field (e.g. "The IP or domain name of the database server") + description -- Set the human-readable description of the field + (e.g. "The IP or domain name of the database server") required_on_create -- If "true", the parameter is required on input stanza creation. required_on_edit -- If "true", the parameter is required on input stanza modification. @@ -70,7 +72,8 @@ def to_python(self, value): def to_string(self, value): """ - Convert the field to a string value that can be returned. Should throw a FieldValidationException if the data is invalid. + Convert the field to a string value that can be returned. Should throw a FieldValidationException if the data is + invalid. Arguments: value -- The value to convert @@ -80,7 +83,6 @@ def to_string(self, value): class BooleanField(Field): - def to_python(self, value): Field.to_python(self, value) @@ -93,14 +95,15 @@ def to_python(self, value): elif str(value).strip().lower() in ["false", "f", "0"]: return False - raise FieldValidationException("The value of '%s' for the '%s' parameter is not a valid boolean" % (str(value), self.name)) + raise FieldValidationException( + "The value of '%s' for the '%s' parameter is not a valid boolean" % (str(value), self.name)) def to_string(self, value): - if value == True: + if value is True: return "1" - elif value == False: + elif value is False: return "0" return str(value) @@ -110,7 +113,6 @@ def get_data_type(self): class DelimitedField(Field): - def __init__(self, name, title, description, delim, required_on_create=True, required_on_edit=False): super(DelimitedField, self).__init__(name, title, description, required_on_create, required_on_edit) self._delim = delim @@ -154,17 +156,8 @@ class DurationField(Field): WEEK = 604800 UNITS = { - 'w': WEEK, - 'week': WEEK, - 'd': DAY, - 'day': DAY, - 'h': HOUR, - 'hour': HOUR, - 'm': MINUTE, - 'min': MINUTE, - 'minute': MINUTE, - 's': 1 - } + 'w': WEEK, 'week': WEEK, 'd': DAY, 'day': DAY, 'h': HOUR, 'hour': HOUR, 'm': MINUTE, 'min': MINUTE, 'minute': + MINUTE, 's': 1} def to_python(self, value): Field.to_python(self, value) @@ -174,7 +167,8 @@ def to_python(self, value): # Make sure the duration could be parsed if m is None: - raise FieldValidationException("The value of '%s' for the '%s' parameter is not a valid duration" % (str(value), self.name)) + raise FieldValidationException( + "The value of '%s' for the '%s' parameter is not a valid duration" % (str(value), self.name)) # Get the units and duration d = m.groupdict() @@ -185,11 +179,13 @@ def to_python(self, value): try: duration = int(d['duration']) except ValueError: - raise FieldValidationException("The duration '%s' for the '%s' parameter is not a valid number" % (d['duration'], self.name)) + raise FieldValidationException( + "The duration '%s' for the '%s' parameter is not a valid number" % (d['duration'], self.name)) # Make sure the units are valid if len(units) > 0 and units not in DurationField.UNITS: - raise FieldValidationException("The unit '%s' for the '%s' parameter is not a valid unit of duration" % (units, self.name)) + raise FieldValidationException( + "The unit '%s' for the '%s' parameter is not a valid unit of duration" % (units, self.name)) # Convert the units to seconds if len(units) > 0: @@ -202,7 +198,6 @@ def to_string(self, value): class FloatField(Field): - def to_python(self, value): Field.to_python(self, value) @@ -227,7 +222,6 @@ def get_data_type(self): class IntegerField(Field): - def to_python(self, value): Field.to_python(self, value) @@ -270,7 +264,8 @@ class IntervalField(Field): # Note that we don't check explicitly for correct numeric values for each # cron field. - cron_rx = re.compile(''' + cron_rx = re.compile( + ''' ( \d{1,2} # A digit. |\d{1,2}-\d{1,2} # A range. @@ -279,22 +274,20 @@ class IntervalField(Field): |\* # The asterisk character. |\*/\d{1,2} # An asterisk followed by a step. ) - ''', - re.VERBOSE - ) + ''', re.VERBOSE) def to_python(self, value): try: # Try parsing the string as an integer. - tmp = int(value) - return value + return int(value) except ValueError: # Try parsing the string as a cron schedule. if self.parse_cron(value): return value - raise FieldValidationException("The value of '{}' for the '{}' parameter is not a valid value".format(value, self.name)) + raise FieldValidationException("The value of '{}' for the '{}' parameter is not a valid value".format( + value, self.name)) def get_data_type(self): return Field.DATA_TYPE_STRING @@ -309,14 +302,14 @@ def parse_cron(self, value): class JsonField(Field): - def to_python(self, value): Field.to_python(self, value) try: return json.loads(value) except (TypeError, ValueError): - raise FieldValidationException("The value of '%s' for the '%s' parameter is not a valid JSON object" % (str(value), self.name)) + raise FieldValidationException( + "The value of '%s' for the '%s' parameter is not a valid JSON object" % (str(value), self.name)) def to_string(self, value): return str(value) @@ -326,7 +319,6 @@ def get_data_type(self): class ListField(Field): - def to_python(self, value): Field.to_python(self, value) @@ -345,7 +337,6 @@ def to_string(self, value): class RangeField(Field): - def __init__(self, name, title, description, low, high, required_on_create=True, required_on_edit=False): super(RangeField, self).__init__(name, title, description, required_on_create, required_on_edit) self.low = low @@ -379,7 +370,6 @@ def get_data_type(self): class RegexField(Field): - def to_python(self, value): Field.to_python(self, value) @@ -404,11 +394,7 @@ class SeverityField(Field): # Note: We ignore "FATAL" severity since Python's logging assigns it the # same value as "CRITICAL". - SEVERITIES = {'DEBUG': 10, - 'INFO': 20, - 'WARN': 30, - 'ERROR': 40, - 'CRITICAL': 50} + SEVERITIES = {'DEBUG': 10, 'INFO': 20, 'WARN': 30, 'ERROR': 40, 'CRITICAL': 50} SEVERITIES_BY_INT = {v: k for k, v in SEVERITIES.iteritems()} @@ -421,7 +407,8 @@ def to_python(self, value): # Did not receive a string for some reason. pass - raise FieldValidationException("The value of '{}' for the '{}' parameter is not a valid value".format(value, self.name)) + raise FieldValidationException("The value of '{}' for the '{}' parameter is not a valid value".format( + value, self.name)) def to_string(self, value): if value in SeverityField.SEVERITIES_BY_INT: @@ -432,8 +419,8 @@ def to_string(self, value): def get_data_type(self): return Field.DATA_TYPE_NUMBER -class VerbosityField(Field): +class VerbosityField(Field): def to_python(self, value): Field.to_python(self, value) @@ -455,4 +442,4 @@ def to_string(self, value): return "" def get_data_type(self): - return Field.DATA_TYPE_NUMBER \ No newline at end of file + return Field.DATA_TYPE_NUMBER diff --git a/splunk_eventgen/splunk_app/lib/xmloutput.py b/splunk_eventgen/splunk_app/lib/xmloutput.py index 5f378d0d..d1277166 100644 --- a/splunk_eventgen/splunk_app/lib/xmloutput.py +++ b/splunk_eventgen/splunk_app/lib/xmloutput.py @@ -1,9 +1,9 @@ -import xml.sax.saxutils +import datetime import logging import logging.handlers import sys -import time -import datetime +import xml.sax.saxutils + from splunk.appserver.mrsparkle.lib.util import make_splunkhome_path @@ -18,8 +18,8 @@ def setupLogger(logger=None, log_format='%(asctime)s %(levelname)s [ModInput] %( logger.propagate = False # Prevent the log messages from being duplicated in the python.log file logger.setLevel(level) - file_handler = logging.handlers.RotatingFileHandler(make_splunkhome_path(['var', 'log', 'splunk', log_name]), - maxBytes=2500000, backupCount=5) + file_handler = logging.handlers.RotatingFileHandler( + make_splunkhome_path(['var', 'log', 'splunk', log_name]), maxBytes=2500000, backupCount=5) formatter = logging.Formatter(log_format) file_handler.setFormatter(formatter) @@ -30,22 +30,21 @@ def setupLogger(logger=None, log_format='%(asctime)s %(levelname)s [ModInput] %( return logger -######################################################################## -# COMMUNICATION WITH SPLUNKD -# We provide a class for printing data out to splunkd. Essentially this -# is just a wrapper on using xml formatted data delivery to splunkd -######################################################################## +######################################################################### +# COMMUNICATION WITH SPLUNKD # +# We provide a class for printing data out to splunkd. Essentially this # +# is just a wrapper on using xml formatted data delivery to splunkd # +######################################################################### class XMLOutputManager(object): """ - This guy handles writing data to splunkd with modular input xml - streaming mode. + This guy handles writing data to splunkd with modular input xml streaming mode. """ def __init__(self, out=sys.stdout): """ - Construct an output manager. - kwargs: - out - represents the stream to print to. Defaults to sys.stdout. + Construct an output manager. + kwargs: + out - represents the stream to print to. Defaults to sys.stdout. """ self.stream_initiated = False self.out = out @@ -72,13 +71,13 @@ def sendData(self, buf, unbroken=None, sourcetype=None, source=None, host=None, args: buf - the buffer of data to send (string). REQUIRED. kwargs: - unbroken - this is a boolean indicating the buf passed is unbroken data if this is True. + unbroken - this is a boolean indicating the buf passed is unbroken data if this is True. Defaults to False (buf is a single event). sourcetype - the sourcetype to assign to the event (string). Defaults to input default. source - the source to assign to the event (string). Defaults to input default. host - the host to assign to the event (string). Defaults to input default. - time - the time to assign to the event (string of UTC UNIX timestamp, - miliseconds supported). Defaults to letting splunkd work it out. + time - the time to assign to the event (string of UTC UNIX timestamp, + milliseconds supported). Defaults to letting splunkd work it out. index - the index into which the data should be stored. Defaults to the input default. """ if not unbroken: @@ -107,7 +106,7 @@ def sendDoneKey(self, sourcetype=None, source=None, host=None, time=None, index= """ Let splunkd know that previously sent, unbroken events are now complete and ready for processing. Typically you will send some data, like chunks of a log file - then when you know you are done, say at the end of the log file you will send a + then when you know you are done, say at the end of the log file you will send a done key to indicate that sent data may be processed for the provided source, sourcetype, host, and index kwargs: @@ -135,4 +134,4 @@ def sendDoneKey(self, sourcetype=None, source=None, host=None, time=None, index= # prints XML error data to be consumed by Splunk def printError(self, s): - self.out.write("{0}".format(xml.sax.saxutils.escape(s))) \ No newline at end of file + self.out.write("{0}".format(xml.sax.saxutils.escape(s))) diff --git a/splunk_eventgen/version.json b/splunk_eventgen/version.json index 07e6fd0f..1047d698 100644 --- a/splunk_eventgen/version.json +++ b/splunk_eventgen/version.json @@ -1 +1 @@ -{"version": "6.3.4"} +{"version": "6.3.5"} \ No newline at end of file diff --git a/tests/.gitignore b/tests/.gitignore index 0d20b648..0dde16b9 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1 +1,2 @@ *.pyc +results/ diff --git a/tests/large/README.md b/tests/large/README.md new file mode 100644 index 00000000..74380daf --- /dev/null +++ b/tests/large/README.md @@ -0,0 +1,12 @@ +Convention: +* Test conf files are located at `conf` folder; +* Sample files are located at `sample` folder; +* Other utils related tools are located at `utils` folder; +* `fileName` in `conf` settings is relative which will write results to folder `tests/large/results`; + +How to add a new functional test: +* Add eventgen conf file in `conf` folder;(`sampleDir = tests/large/sample` should be in the conf) +* Add sample file defined in above eventgen conf in folder `sample`; +* Add a new functional test `py` file and add test case; +* Use `eventgen_test_helper` fixture to create a helper instance and use `get_events()` to get events generated; +* Pass `timeout=60` if you want to stop eventgen instance after 60s; diff --git a/tests/large/conf/eventgen_replay.conf b/tests/large/conf/eventgen_replay.conf new file mode 100755 index 00000000..c919f072 --- /dev/null +++ b/tests/large/conf/eventgen_replay.conf @@ -0,0 +1,14 @@ +[replay] +sampleDir = tests/large/sample +mode = replay +sampletype = raw +outputMode = stdout +end = 1 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = replaytimestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_replay_backfill.conf b/tests/large/conf/eventgen_replay_backfill.conf new file mode 100644 index 00000000..c8e0b1ca --- /dev/null +++ b/tests/large/conf/eventgen_replay_backfill.conf @@ -0,0 +1,15 @@ +[replay] +sampleDir = tests/large/sample +backfill = -5s +sampletype = raw +outputMode = stdout +mode = replay +end = 2 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = replaytimestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_replay_csv.conf b/tests/large/conf/eventgen_replay_csv.conf new file mode 100755 index 00000000..a00ca925 --- /dev/null +++ b/tests/large/conf/eventgen_replay_csv.conf @@ -0,0 +1,10 @@ +[timeorder] +sampleDir = tests/large/sample +mode = replay +sampletype = csv +timeField = _time +outputMode = stdout + +token.0.token = \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2} +token.0.replacementType = replaytimestamp +token.0.replacement = %Y-%m-%dT%H:%M:%S diff --git a/tests/large/conf/eventgen_replay_end_1.conf b/tests/large/conf/eventgen_replay_end_1.conf new file mode 100755 index 00000000..f9295a8f --- /dev/null +++ b/tests/large/conf/eventgen_replay_end_1.conf @@ -0,0 +1,15 @@ +[replay] +sampleDir = tests/large/sample +mode = replay +earliest = -5s +sampletype = raw +outputMode = stdout +end = 2 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = replaytimestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_replay_end_2.conf b/tests/large/conf/eventgen_replay_end_2.conf new file mode 100755 index 00000000..afbcb35a --- /dev/null +++ b/tests/large/conf/eventgen_replay_end_2.conf @@ -0,0 +1,15 @@ +[replay] +sampleDir = tests/large/sample +mode = replay +earliest = -5s +sampletype = raw +outputMode = stdout +end = -1 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = replaytimestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_replay_timeMultiple.conf b/tests/large/conf/eventgen_replay_timeMultiple.conf new file mode 100755 index 00000000..c51ff32b --- /dev/null +++ b/tests/large/conf/eventgen_replay_timeMultiple.conf @@ -0,0 +1,14 @@ +[replay] +sampleDir = tests/large/sample +mode = replay +sampletype = raw +outputMode = stdout +timeMultiple = 0.5 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = replaytimestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_sample.conf b/tests/large/conf/eventgen_sample.conf new file mode 100755 index 00000000..657ec987 --- /dev/null +++ b/tests/large/conf/eventgen_sample.conf @@ -0,0 +1,15 @@ +[sample] +sampleDir = tests/large/sample +mode = sample +earliest = -15s +sampletype = raw +outputMode = stdout +end = 1 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_sample_backfill.conf b/tests/large/conf/eventgen_sample_backfill.conf new file mode 100755 index 00000000..8c9d56ac --- /dev/null +++ b/tests/large/conf/eventgen_sample_backfill.conf @@ -0,0 +1,15 @@ +[sample] +sampleDir = tests/large/sample +mode = sample +backfill = -15s +sampletype = raw +outputMode = stdout +end = 1 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_sample_breaker.conf b/tests/large/conf/eventgen_sample_breaker.conf new file mode 100755 index 00000000..99a41ded --- /dev/null +++ b/tests/large/conf/eventgen_sample_breaker.conf @@ -0,0 +1,14 @@ +[breakersample] +sampleDir = tests/large/sample +outputMode = file +fileName = tests/large/results/eventgen_sample_breaker.result +count = 3 +earliest = -3s +latest = now +interval = 3 +breaker = ^\d{14}\.\d{6} +end = 1 + +token.0.token = ^(\d{14})\.\d{6} +token.0.replacementType = timestamp +token.0.replacement = %Y%m%d%H%M%S diff --git a/tests/large/conf/eventgen_sample_count.conf b/tests/large/conf/eventgen_sample_count.conf new file mode 100755 index 00000000..688c4b0f --- /dev/null +++ b/tests/large/conf/eventgen_sample_count.conf @@ -0,0 +1,16 @@ +[sample] +sampleDir = tests/large/sample +mode = sample +earliest = -15s +sampletype = raw +outputMode = stdout +end = 1 +count = 5 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_sample_csv.conf b/tests/large/conf/eventgen_sample_csv.conf new file mode 100755 index 00000000..18065dac --- /dev/null +++ b/tests/large/conf/eventgen_sample_csv.conf @@ -0,0 +1,14 @@ +[timeorder] +sampleDir = tests/large/sample +mode = sample +sampletype = csv +outputMode = stdout +end = 1 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_sample_earliest.conf b/tests/large/conf/eventgen_sample_earliest.conf new file mode 100755 index 00000000..8c505b14 --- /dev/null +++ b/tests/large/conf/eventgen_sample_earliest.conf @@ -0,0 +1,16 @@ +[sample] +sampleDir = tests/large/sample +mode = sample +earliest = -15s +sampletype = raw +outputMode = file +fileName = tests/large/results/eventgen_sample_earliest.result +end = 1 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_sample_end.conf b/tests/large/conf/eventgen_sample_end.conf new file mode 100755 index 00000000..9918bc79 --- /dev/null +++ b/tests/large/conf/eventgen_sample_end.conf @@ -0,0 +1,16 @@ +[sample] +sampleDir = tests/large/sample +mode = sample +earliest = -15s +sampletype = raw +outputMode = file +fileName = tests/large/results/eventgen_sample_end.result +end = 1 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_sample_interval.conf b/tests/large/conf/eventgen_sample_interval.conf new file mode 100755 index 00000000..74d95c8a --- /dev/null +++ b/tests/large/conf/eventgen_sample_interval.conf @@ -0,0 +1,15 @@ +[sample] +sampleDir = tests/large/sample +mode = sample +sampletype = raw +outputMode = file +fileName = tests/large/results/eventgen_sample_interval.result +interval = 10 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_sample_latest.conf b/tests/large/conf/eventgen_sample_latest.conf new file mode 100755 index 00000000..00ff18aa --- /dev/null +++ b/tests/large/conf/eventgen_sample_latest.conf @@ -0,0 +1,16 @@ +[sample] +sampleDir = tests/large/sample +mode = sample +latest = +15s +sampletype = raw +outputMode = file +fileName = tests/large/results/eventgen_sample_latest.result +end = 1 + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%d %H:%M:%S + +token.1.token = @@integer +token.1.replacementType = random +token.1.replacement = integer[0:10] diff --git a/tests/large/conf/eventgen_token_replacement.conf b/tests/large/conf/eventgen_token_replacement.conf new file mode 100755 index 00000000..9b521e4b --- /dev/null +++ b/tests/large/conf/eventgen_token_replacement.conf @@ -0,0 +1,62 @@ +[tokenreplacement.sample] +sampleDir = tests/large/sample +mode = sample +sampletype = raw +outputMode = stdout +end = 1 + +token.0.token = "start":"(\d+) +token.0.replacementType = timestamp +token.0.replacement = %s + +token.1.token = "cp":"([\d\.]+) +token.1.replacementType = file +token.1.replacement = tests/large/sample/cp.csv + +token.2.token = "country":"(\w+) +token.2.replacementType = mvfile +token.2.replacement = tests/large/sample/city.csv:1 + +token.3.token = "city":"(\w+) +token.3.replacementType = file +token.3.replacement = tests/large/sample/city.csv:2 + +token.4.token = "lat":"(-?\d+.\d+) +token.4.replacementType = file +token.4.replacement = tests/large/sample/city.csv:4 + +token.5.token = "long":"(-?\d+.\d+) +token.5.replacementType = file +token.5.replacement = tests/large/sample/city.csv:5 + +token.6.token = "id":"([\w\-]+) +token.6.replacementType = file +token.6.replacement = tests/large/sample/id.csv + +token.7.token = "bytes":"(\d+) +token.7.replacementType = random +token.7.replacement = integer[40:5000] + +token.8.token = "cliIP":"(\d+.\d+.\d+.\d+) +token.8.replacementType = file +token.8.replacement = tests/large/sample/ip.csv + +token.9.token = "lastByte":"(\d+) +token.9.replacementType = static +token.9.replacement = 0 + +token.10.token = "receiver_id":"(\d*) +token.10.replacementType = integerid +token.10.replacement = 1 + +token.11.token = "Ak_IP":"(\d+.\d+.\d+.\d+) +token.11.replacementType = random +token.11.replacement = ipv4 + +token.12.token = "forward-origin-ip":"(\d+.\d+.\d+.\d+) +token.12.replacementType = random +token.12.replacement = ipv6 + +token.13.token = "end-user-ip":"(\d+.\d+.\d+.\d+) +token.13.replacementType = random +token.13.replacement = mac diff --git a/tests/large/conftest.py b/tests/large/conftest.py new file mode 100644 index 00000000..60663dd6 --- /dev/null +++ b/tests/large/conftest.py @@ -0,0 +1,18 @@ +import pytest + +from utils.eventgen_test_helper import EventgenTestHelper + + +@pytest.fixture +def eventgen_test_helper(): + """Returns a function to create EventgenTestHelper instance based on config file""" + created_instances = [] + + def _create_eventgen_test_helper_instance(conf, timeout=None): + instance = EventgenTestHelper(conf, timeout) + created_instances.append(instance) + return instance + yield _create_eventgen_test_helper_instance + + for instance in created_instances: + instance.tear_down() diff --git a/tests/large/results/__init__.py b/tests/large/results/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/large/sample/breakersample b/tests/large/sample/breakersample new file mode 100755 index 00000000..51304b28 --- /dev/null +++ b/tests/large/sample/breakersample @@ -0,0 +1,9 @@ +20110414114247.083068 +PercentProcessorTime=@@proc_time +PercentUserTime=37 +wmi_type=CPUTime + +20110414114247.083068 +PercentProcessorTime=100 +PercentUserTime=37 +wmi_type=CPUTime diff --git a/tests/large/sample/city.csv b/tests/large/sample/city.csv new file mode 100644 index 00000000..e9a15c34 --- /dev/null +++ b/tests/large/sample/city.csv @@ -0,0 +1,7472 @@ +US,ATLANTA,GA,33.7486,-84.3884,23.74.2.12 +US,WASHINGTON,DC,38.9102,-77.0179,204.93.39.36 +GB,LONDON,EN,51.50,-0.12,88.221.87.112 +TW,TAIPEI,"",25.02,121.45,61.220.62.171 +US,AUSTIN,TX,30.2669,-97.7429,23.215.15.32 +AU,BRISBANE,QLD,-27.50,153.02,210.11.142.64 +US,LOSANGELES,CA,33.9733,-118.2487,173.223.52.67 +CA,VANCOUVER,BC,49.25,-123.13,24.244.17.205 +CA,MONTREAL,QC,45.50,-73.58,72.246.43.237 +DE,FRANKFURT,HE,50.12,8.68,2.20.142.166 +US,POTTSTOWN,PA,40.2616,-75.6182,184.26.44.42 +UA,KIEV,"",50.43,30.52,80.239.222.190 +CA,TORONTO,ON,43.67,-79.42,165.254.48.150 +US,MILILANI,HI,21.4601,-157.9603,23.67.56.205 +EC,GUAYAQUIL,"",-2.17,-79.90,23.74.2.7 +CN,GUANGZHOU,GD,23.12,113.25,72.246.191.16 +MX,GUADALAJARA,JAL,20.67,-103.33,107.14.32.235 +VN,SAIGON,"",10.75,106.67,184.84.239.186 +US,NEWYORK,NY,40.7500,-73.9967,209.170.113.237 +US,PRINEVILLE,OR,44.3258,-120.6504,23.79.240.37 +CA,CALGARY,AB,51.08,-114.08,24.244.17.197 +US,SANANTONIO,TX,29.4697,-98.5294,165.254.96.242 +US,SAINTPETERSBURG,FL,27.7710,-82.6368,23.74.2.12 +US,MOUNTAINVIEW,CA,37.4154,-122.0585,63.80.12.225 +US,CHARLOTTESVILLE,VA,38.0464,-78.4686,184.26.44.42 +US,JACKSONVILLE,FL,30.3383,-81.7706,23.79.240.48 +US,DALLAS,TX,32.7874,-96.7989,23.212.53.64 +US,CHICAGO,IL,41.8643,-87.645,23.79.255.153 +IN,KOLKATA,WB,22.57,88.37,23.57.76.18 +US,ROSEVILLE,CA,38.7399,-121.2479,23.61.195.149 +US,PATERSON,NJ,40.9126,-74.171,184.51.125.79 +DE,HERBORN,HE,50.68,8.32,23.14.94.228 +GE,TBILISI,"",41.72,44.78,80.15.235.171 +US,GOLETA,CA,34.4356,-119.8269,184.50.26.179 +LV,RIGA,"",56.95,24.10,2.21.240.40 +NZ,AUCKLAND,"",-36.87,174.77,184.28.126.7 +KR,ANYANG,"",37.39,126.93,125.56.214.147 +HK,HONGKONG,"",22.28,114.15,219.76.10.103 +IT,MILANO,"",45.47,9.20,193.45.15.199 +US,SUNNYVALE,CA,37.3873,-122.0158,23.212.52.82 +US,INDEPENDENCE,MO,39.1129,-94.4077,23.77.234.11 +DE,WILHELMSHAVEN,NI,53.52,8.13,2.20.142.166 +US,RIVERFOREST,IL,41.8950,-87.8194,23.67.60.220 +US,REDWOODCITY,CA,37.4611,-122.2355,23.61.195.150 +IN,BHOPAL,MP,23.27,77.40,96.17.180.175 +CN,NANNING,GX,22.82,108.32,184.51.199.145 +CN,BEIJING,BJ,39.90,116.41,184.51.199.132 +US,FRESNO,CA,36.8419,-119.7952,23.212.52.79 +US,MCKINNEY,TX,33.2109,-96.5677,107.14.43.30 +FR,SAINTDENIS,"",48.93,2.37,217.89.107.179 +US,MODESTO,CA,37.6733,-121.0107,96.17.12.44 +UA,KERCH,CRIMEA,45.36,36.48,2.22.52.109 +US,WILMINGTON,CA,33.7841,-118.2613,184.87.195.109 +SG,SINGAPORE,"",1.29,103.86,23.75.23.135 +US,GERMANTOWN,MD,39.1292,-77.2953,23.192.161.16 +US,SAINTLOUIS,MO,38.6312,-90.1926,96.17.14.16 +TH,BANGKOK,"",13.75,100.52,23.14.94.228 +US,PORTLAND,OR,45.4978,-122.6937,67.131.104.14 +US,UNIONCITY,CA,37.5970,-122.059,96.17.12.44 +US,SEATTLE,WA,47.6115,-122.3343,184.27.179.187 +US,FORTCOLLINS,CO,40.5917,-105.129,63.235.21.141 +US,ROCHESTER,NY,43.1544,-77.6156,107.14.38.227 +PH,ROOSEVELT,"",12.73,123.70,202.78.83.175 +US,SALTLAKECITY,UT,40.7566,-111.8992,23.212.53.75 +AU,RIVERWOOD,NSW,-33.95,151.05,23.62.8.25 +US,GLENDALE,CA,34.1697,-118.2902,184.87.195.99 +AU,CANBERRA,ACT,-35.28,149.22,60.254.143.114 +US,SPRINGFIELD,MO,37.2155,-93.2981,23.77.234.11 +US,KANSASCITY,MO,39.1034,-94.6,23.63.227.227 +US,MARTIN,TN,36.3557,-88.8417,23.79.240.36 +US,BRIDGEVIEW,IL,41.7407,-87.8064,23.67.60.222 +US,HOMESTEAD,FL,25.4848,-80.5094,23.79.240.48 +ZA,CAPETOWN,"",-33.92,18.42,41.193.163.53 +US,WAUKEE,IA,41.6100,-93.8635,23.67.60.217 +FR,NICE,"",43.70,7.25,2.16.117.190 +US,WESTPALMBEACH,FL,26.7174,-80.0695,184.51.207.103 +US,JACKSON,MS,32.2896,-90.1841,23.79.240.36 +US,BUFFALO,NY,42.8954,-78.8862,23.63.227.227 +US,INDIANAPOLIS,IN,39.7745,-86.1096,65.113.249.8 +DE,DUSSELDORF,NW,51.22,6.77,92.122.207.164 +MX,MEXICOCITY,DIF,19.43,-99.14,23.216.10.54 +ES,MADRID,"",40.40,-3.68,92.123.73.233 +CN,FUZHOU,FJ,26.08,119.30,72.246.191.16 +US,DETROIT,MI,42.3465,-83.0598,23.62.100.152 +US,SANTAFE,NM,35.7998,-105.9892,184.84.180.97 +US,MADISON,WI,43.0733,-89.4012,184.85.215.165 +US,GLASGOW,KY,36.9602,-85.9175,65.113.249.8 +US,FAIRFAX,SC,32.8821,-81.3268,64.86.201.118 +AU,SYDNEY,NSW,-33.88,151.22,184.28.17.55 +US,RANTOUL,IL,40.3044,-88.1569,23.67.60.223 +US,NORMAN,OK,35.2227,-97.4395,23.215.15.9 +IN,BHANDUP,MH,19.15,72.93,23.57.69.157 +GB,EALING,EN,51.50,-0.32,173.222.211.203 +US,MILWAUKEE,WI,43.0386,-87.9067,23.74.8.24 +US,BROOKLYN,NY,40.6944,-73.9902,184.26.44.42 +JP,TOKYO,13,35.69,139.75,23.15.1.15 +DE,HAMBURG,HH,53.55,10.00,194.25.95.214 +US,PHOENIX,AZ,33.4486,-112.0733,184.50.26.179 +US,RALEIGH,NC,35.7750,-78.6336,184.27.45.157 +LT,VILNIUS,"",54.68,25.32,2.21.240.40 +US,ORLANDO,FL,28.5418,-81.3736,23.33.186.101 +US,FREMONT,CA,37.5710,-121.9858,23.61.195.150 +CA,EDMONTON,AB,53.55,-113.50,65.113.249.11 +US,SMYRNA,GA,33.8714,-84.4998,184.51.35.226 +MY,KUALALUMPUR,"",3.17,101.70,58.26.185.125 +ES,VALENCIA,"",39.47,-0.37,213.248.113.118 +US,TEMPE,AZ,33.4148,-111.9088,184.50.26.201 +US,MIAMI,FL,25.7738,-80.1936,23.79.240.48 +BG,STARAZAGORA,"",42.42,25.63,23.62.237.133 +KE,NAIROBI,"",-1.28,36.82,95.101.2.112 +UA,KHARKIV,"",50.00,36.25,2.22.52.102 +US,MARIETTA,GA,33.9527,-84.5502,23.79.240.36 +FR,PARIS,"",48.87,2.33,23.212.108.8 +US,HUMBOLDT,IA,42.7370,-94.1578,23.63.227.214 +US,OAKLAND,NJ,41.0312,-74.241,184.51.125.79 +GB,BIRMINGHAM,EN,52.47,-1.92,23.67.255.106 +US,SANFRANCISCO,CA,37.7795,-122.4195,96.17.12.44 +FR,LYON,"",45.75,4.85,23.62.237.137 +RU,TOMSK,"",56.50,84.97,2.21.240.40 +DE,NEUISENBURG,HE,50.05,8.70,77.67.27.231 +US,RICHLAND,WA,46.3844,-119.3775,184.27.179.187 +US,HIALEAH,FL,25.8579,-80.2783,23.79.240.36 +US,TACOMA,WA,47.2534,-122.4432,23.212.59.64 +US,DURHAM,NC,35.9993,-78.8978,209.18.41.23 +AU,MELBOURNE,VIC,-37.82,144.97,60.254.143.211 +LU,LUXEMBOURG,"",49.61,6.13,77.67.27.250 +CH,ZURICH,"",47.37,8.55,194.25.95.225 +US,MAULDIN,SC,34.7791,-82.3072,23.79.240.48 +GB,RENFREW,SC,55.87,-4.37,88.221.87.94 +US,DIAMONDBAR,CA,33.9944,-117.8149,184.50.26.179 +US,ASHBURN,VA,39.0438,-77.4879,96.6.47.106 +US,OREM,UT,40.3142,-111.7099,184.84.180.68 +US,MENLOPARK,CA,37.4524,-122.1842,23.212.52.88 +US,TORRANCE,CA,33.8331,-118.3144,23.216.10.78 +US,SANDIEGO,CA,32.7253,-117.1721,63.151.119.16 +IN,HYDERABAD,AP,17.38,78.47,23.57.69.156 +US,WARRENSBURG,MO,38.8247,-93.6796,204.93.47.216 +US,SANLORENZO,CA,37.6786,-122.133,184.84.180.101 +DE,KOLN,NW,50.93,6.95,23.14.94.228 +VN,HANOI,"",21.03,105.85,23.76.205.111 +US,BOISE,ID,43.6139,-116.2025,206.104.149.146 +US,CANALWINCHESTER,OH,39.8265,-82.7973,96.17.9.14 +US,SACRAMENTO,CA,38.5819,-121.4935,96.17.12.48 +US,ELOY,AZ,32.6521,-111.6069,173.223.52.70 +US,BOWLINGGREEN,KY,37.1031,-86.4201,107.14.38.224 +AU,CARLINGFORD,NSW,-33.78,151.05,23.62.8.25 +KR,SEOUL,"",37.57,127.00,61.111.58.43 +US,REDMOND,WA,47.6833,-122.1231,184.27.179.159 +RO,DEVA,"",45.88,22.90,81.196.26.236 +IN,BANGALORE,KA,12.98,77.58,122.178.225.70 +RU,MOSCOW,"",55.75,37.58,217.212.227.25 +US,BEDFORD,PA,39.9363,-78.5519,205.185.195.170 +US,MOUNTEPHRAIM,NJ,39.8811,-75.0919,184.26.44.38 +DE,BERLIN,BE,52.52,13.40,23.14.94.220 +SE,STOCKHOLM,AB,59.33,18.05,2.21.240.40 +US,GASTONIA,NC,35.2205,-81.2501,63.141.200.241 +US,MAITLAND,FL,28.6318,-81.3625,23.33.186.101 +US,PUYALLUP,WA,47.1905,-122.3289,23.212.59.90 +US,COEURDALENE,ID,47.6719,-116.5794,107.14.43.30 +DE,REGENSBURG,BY,49.02,12.10,194.25.95.214 +PL,WARSAW,"",52.25,21.00,2.22.52.109 +CN,SHENYANG,LN,41.80,123.41,184.50.87.176 +DE,HEILBRONN,BW,49.14,9.22,92.122.215.89 +US,SANTAROSA,CA,38.4507,-122.7923,96.17.12.44 +US,SANDY,UT,40.5769,-111.8884,63.151.119.25 +AR,MUNRO,"",-34.53,-58.55,80.239.222.167 +US,SANTACLARA,CA,37.3519,-121.952,23.204.109.61 +MT,MELITA,"",35.89,14.40,193.45.15.199 +IE,DUBLIN,"",53.33,-6.25,88.221.222.33 +IN,NEWDELHI,DL,28.60,77.20,23.57.69.157 +US,DESMOINES,IA,41.6006,-93.6087,23.67.60.223 +US,GREENVILLE,NC,35.6116,-77.3732,184.28.17.76 +AT,EGGENBURG,"",48.63,15.82,195.145.147.107 +US,WALNUT,CA,34.0203,-117.8647,184.50.26.179 +US,SALEM,OR,44.9053,-122.9167,23.212.59.63 +US,CENTREVILLE,VA,38.8530,-77.4732,23.67.242.139 +PK,FAZAL,"",26.63,69.53,23.5.165.168 +JP,NAGOYA,23,35.17,136.92,72.246.191.19 +RU,PROGRESS,"",53.88,37.85,80.239.222.169 +US,LEXINGTON,KY,38.0142,-84.4842,23.74.8.24 +DK,COPENHAGEN,"",55.67,12.58,2.21.240.61 +BR,RIODEJANEIRO,RJ,-22.90,-43.23,177.159.174.13 +US,CANYONCOUNTRY,CA,34.4009,-118.3941,184.50.26.194 +US,NASHVILLE,TN,36.1649,-86.7761,23.67.60.223 +US,FULTON,MO,38.8555,-91.9568,23.79.255.153 +US,MONROE,LA,32.5324,-92.1046,65.113.249.8 +CA,REGINA,SK,50.45,-104.62,184.27.179.181 +UA,LVIV,"",49.83,24.00,23.14.94.224 +US,MORGANHILL,CA,37.2101,-121.5392,23.216.10.78 +US,HAYS,KS,38.8338,-99.3297,165.254.96.248 +US,PASADENA,CA,34.1465,-118.1393,23.216.10.54 +LV,ILGUCIEMS,"",56.97,24.07,2.21.240.61 +US,SANJOSE,CA,37.3435,-121.8887,23.61.195.165 +ID,JAKARTA,"",-6.17,106.80,23.0.162.46 +US,NEWBALTIMORE,MI,42.6814,-82.776,23.67.60.222 +US,HOUSTON,TX,29.7634,-95.3634,23.215.15.22 +RS,BELGRADE,"",44.82,20.47,23.62.237.135 +IN,CHENNAI,TN,13.08,80.28,23.205.118.106 +US,MENOMONEEFALLS,WI,43.1490,-88.1221,65.113.249.8 +US,WINDER,GA,33.9995,-83.6956,23.79.240.36 +US,SHERMANOAKS,CA,34.1460,-118.4632,184.50.26.203 +SA,RIYADH,"",24.64,46.77,80.239.237.231 +US,NORTHRIDGE,CA,34.2385,-118.5501,184.50.26.179 +US,FORTWORTH,TX,32.7254,-97.3208,96.17.177.63 +US,STAMFORD,CT,41.0531,-73.5379,65.113.249.11 +GB,BELFAST,NI,54.58,-5.93,23.212.108.28 +US,GRANDFORKS,ND,47.8810,-97.0607,107.14.38.217 +US,HOMEWOOD,IL,41.5602,-87.657,23.67.60.223 +US,LOUISVILLE,KY,38.2545,-85.7595,107.14.38.227 +US,SANTACRUZ,CA,37.0412,-122.124,23.61.195.163 +HU,BUDAPEST,"",47.50,19.08,46.33.70.104 +US,MILESCITY,MT,46.3777,-105.7778,23.215.15.32 +US,PALMDALE,CA,34.4834,-118.0804,184.50.26.179 +DE,DARMSTADT,HE,49.87,8.65,194.25.95.212 +GB,CROYDON,EN,51.38,-0.10,23.67.255.158 +AR,BUENOSAIRES,"",-34.59,-58.67,190.98.167.220 +FR,AMIENS,"",49.90,2.30,2.20.243.45 +US,NOVI,MI,42.4713,-83.5253,184.26.93.116 +US,FREEPORT,NY,40.6517,-73.5837,184.26.44.38 +US,BALTIMORE,MD,39.2940,-76.6226,23.67.242.139 +AU,PERTH,WA,-31.93,115.83,184.86.223.76 +US,LAKEJACKSON,TX,29.0424,-95.4739,23.215.15.9 +US,STATECOLLEGE,PA,40.8020,-77.8329,63.216.54.216 +US,NAPA,CA,38.3929,-122.2917,23.212.52.79 +US,BRUNSWICK,OH,41.2414,-81.829,107.14.32.235 +US,ELCENTRO,CA,32.7712,-115.5933,184.50.26.179 +US,CHULAVISTA,CA,32.6403,-117.0834,23.220.149.114 +IL,HAIFA,"",32.82,34.99,212.143.162.162 +US,GEORGETOWN,TX,30.6233,-97.6645,204.2.223.90 +US,SAGINAW,MI,43.4083,-83.8878,23.63.227.227 +BG,SOFIA,"",42.68,23.32,23.62.237.133 +CA,BURNABY,BC,49.25,-122.95,24.244.17.197 +US,CULVERCITY,CA,33.9886,-118.3988,165.254.51.142 +CA,OTTAWA,ON,45.42,-75.70,107.14.38.227 +IT,ROME,"",41.90,12.48,95.101.34.109 +BR,BRASILIA,DF,-15.78,-47.92,2.22.52.102 +US,SCOTTSDALE,AZ,33.5251,-111.8956,63.226.34.173 +JP,MARUNOUCHI,13,35.68,139.77,104.74.70.105 +RO,CONSTANTA,"",44.18,28.65,81.196.26.236 +US,TEMECULA,CA,33.4939,-117.1475,184.50.26.179 +US,SARALAND,AL,30.8789,-88.1101,96.17.153.162 +PK,LAHORE,"",31.57,74.32,79.140.94.234 +US,NEWARK,CA,37.5187,-122.045,96.17.12.48 +US,OLYMPIA,WA,46.9755,-122.8721,184.84.180.101 +US,RENTON,WA,47.4624,-122.211,23.212.59.85 +PH,MAKATI,"",14.57,121.03,58.71.107.120 +FR,GRENOBLE,"",45.17,5.72,2.20.243.42 +DE,ROTTWEIL,BW,48.17,8.62,194.25.95.225 +US,REDFORD,MI,42.3767,-83.2863,69.22.154.212 +US,SPOKANE,WA,47.6670,-117.4381,206.104.149.133 +US,KALAMAZOO,MI,42.2663,-85.5617,23.63.227.214 +JP,OSAKA,27,34.67,135.50,72.246.184.89 +US,BURLINGTON,NJ,40.0691,-74.8276,184.26.44.42 +IN,MUMBAI,MH,18.98,72.83,124.124.252.159 +US,SANGABRIEL,CA,34.1144,-118.0896,23.215.15.9 +PT,LISBON,"",38.72,-9.13,92.122.127.109 +US,PALOALTO,CA,37.4439,-122.1504,184.84.180.101 +GB,MANCHESTER,EN,53.50,-2.22,23.67.255.158 +US,LEWISVILLE,TX,33.0463,-96.9939,107.14.43.29 +US,PINELLASPARK,FL,27.8427,-82.6999,63.141.200.248 +US,GRANDJUNCTION,CO,39.0723,-108.5429,184.85.215.165 +US,WYOMING,MI,42.8655,-85.6221,23.67.60.223 +US,ROSEMEAD,CA,34.0646,-118.0833,23.216.10.54 +US,ROCKYRIVER,OH,41.4702,-81.8524,72.247.10.237 +AU,ADELAIDE,SA,-34.93,138.60,23.205.117.14 +DE,BAYREUTH,BY,49.95,11.58,195.145.147.107 +US,QUINCY,WA,47.1872,-119.8129,184.27.45.150 +US,HUNTINGTONPARK,CA,33.9770,-118.2172,184.87.195.109 +US,CARY,NC,35.7524,-78.7781,209.18.41.27 +DE,ESCHBORN,HE,50.13,8.55,92.122.207.179 +US,LYNN,MA,42.4611,-70.947,23.67.244.240 +US,BIXBY,OK,35.9022,-95.8422,23.215.15.22 +AE,DUBAI,"",25.25,55.28,173.223.52.70 +DE,SIEGEN,NW,50.87,8.03,195.145.147.109 +US,PECOS,TX,31.4465,-103.7134,23.74.8.24 +CA,JOLIETTE,QC,46.03,-73.43,67.69.197.95 +US,DENVER,CO,39.7393,-104.9844,23.215.15.32 +CN,SHIJIAZHUANG,HE,38.04,114.48,72.246.191.19 +CN,URUMQI,XJ,43.80,87.58,72.246.191.19 +DE,MUNICH,BY,48.15,11.58,84.53.146.39 +US,SWEDESBORO,NJ,39.7570,-75.3338,72.247.10.237 +US,MEDFORD,MA,42.4184,-71.1069,184.25.109.196 +US,SHREVEPORT,LA,32.5051,-93.7448,96.17.153.157 +DE,AUGSBURG,BY,48.37,10.88,195.145.147.101 +BR,CURITIBA,PR,-25.42,-49.25,189.75.165.189 +US,POMPANOBEACH,FL,26.2349,-80.1201,23.79.240.36 +BR,PORTOALEGRE,RS,-30.03,-51.20,189.75.165.189 +PR,SANJUAN,"",18.4697,-66.1179,23.61.195.163 +BD,DHAKA,"",23.72,90.41,165.254.134.201 +LK,COLOMBO,"",6.93,79.85,23.220.148.146 +US,SANYSIDRO,CA,32.7154,-117.1565,23.220.149.124 +US,IRVINE,CA,33.6880,-117.7988,184.50.26.201 +US,LYNNWOOD,WA,47.8111,-122.2834,184.27.179.159 +US,BAYTOWN,TX,29.7803,-94.894,23.212.53.75 +US,AMARILLO,TX,35.2118,-101.7582,23.5.164.146 +US,MOUNTJULIET,TN,36.1974,-86.4365,23.79.240.36 +US,BAYCITY,MI,43.5968,-83.9583,23.63.227.214 +US,CLEVELAND,OH,41.4995,-81.6959,23.74.8.24 +CA,BRANDON,MB,49.83,-99.95,23.74.8.24 +US,CONYERS,GA,33.7241,-83.9735,23.79.240.36 +US,TAMPA,FL,27.9475,-82.4588,165.254.205.7 +US,LUSBY,MD,38.3848,-76.4416,23.192.161.21 +US,HARRIMAN,TN,35.9599,-84.4439,23.79.240.48 +DE,STUTTGART,BW,48.77,9.18,84.53.146.34 +US,SANMATEO,CA,37.5741,-122.3193,69.22.166.208 +US,WEATHERFORD,TX,32.8532,-97.696,204.93.47.216 +US,RICHMOND,VA,37.5539,-77.4608,63.130.161.140 +BE,BRUSSELS,"",50.83,4.33,23.62.100.152 +US,GROVE,OK,36.5736,-94.7059,23.5.164.143 +US,REDDING,CA,40.4417,-122.9863,23.216.10.54 +US,BLOOMINGTON,IL,40.4766,-88.992,23.67.60.223 +US,SIOUXFALLS,SD,43.5503,-96.7002,107.14.38.217 +US,KILLEEN,TX,31.1169,-97.7264,107.14.43.30 +US,LONGVIEW,WA,46.2098,-123.0644,23.212.59.85 +KZ,ALMATY,"",43.25,76.95,23.14.94.224 +JP,IZUMO,32,35.37,132.77,23.3.74.113 +US,DALTON,GA,34.7698,-84.9703,63.216.54.236 +US,RIVERSIDE,CA,33.9951,-117.3732,23.216.10.54 +US,OXFORD,OH,39.4851,-84.7501,107.14.38.224 +DE,LEIPZIG,SN,51.30,12.33,80.157.150.169 +DE,MAINZ,RP,50.00,8.27,194.25.95.214 +GB,HUDDERSFIELD,EN,53.65,-1.78,88.221.87.94 +NZ,TAURANGA,"",-37.69,176.17,219.88.186.164 +RO,TIMISOARA,"",45.76,21.23,23.212.108.28 +HU,TOROKBALINT,"",47.43,18.92,213.198.95.213 +DE,BAYERN,BY,47.80,12.53,2.16.217.206 +US,FOUNTAINVALLEY,CA,33.7104,-117.9513,107.14.44.185 +US,VISTA,CA,33.1789,-117.2437,63.151.119.16 +US,REYNOLDSBURG,OH,39.9581,-82.7839,23.212.53.75 +US,CHEYENNE,WY,41.1301,-104.8689,69.31.59.63 +US,TUCSON,AZ,32.2167,-110.9709,184.50.26.204 +US,KIRKLAND,WA,47.6755,-122.1871,23.61.195.163 +US,EAGLERIVER,AK,61.1936,-149.321,96.17.108.26 +CO,BOGOTA,"",4.60,-74.08,23.74.2.7 +US,ELPASO,TX,31.7603,-106.4799,107.14.43.29 +US,OMAHA,NE,41.2596,-95.9374,23.74.8.8 +CA,NANAIMO,BC,49.15,-123.92,184.27.179.159 +US,MILPITAS,CA,37.4486,-121.8587,96.17.12.48 +US,NEWHARTFORD,NY,43.0600,-75.2864,107.14.38.227 +UA,UKRAINA,"",47.33,36.27,2.20.142.166 +US,CHARLOTTE,NC,35.2287,-80.8458,63.151.29.15 +US,GARDENGROVE,CA,33.7860,-117.9318,184.50.26.201 +US,APPLETON,WI,44.2816,-88.3849,107.14.38.224 +US,LANCASTER,CA,34.7349,-118.1508,184.50.26.204 +BR,SAOPAULO,SP,-23.53,-46.62,177.159.181.174 +CN,TAIYUAN,SX,37.87,112.56,72.246.191.16 +US,CICERO,IL,41.8443,-87.7585,23.67.60.222 +US,ELKIN,NC,36.3086,-80.843,209.18.41.27 +US,MOUNTVERNON,WA,48.4305,-122.4357,184.27.179.159 +AZ,BAKI,"",40.37,49.88,80.239.149.123 +US,LARAMIE,WY,41.3416,-105.6973,23.212.53.64 +US,ALBANY,OR,44.6313,-123.0676,184.27.179.159 +US,ADDISON,IL,41.9314,-88.011,107.14.38.224 +RU,CHITA,"",52.03,113.55,2.21.240.61 +US,GAMBRILLS,MD,38.9852,-76.6657,23.192.161.30 +US,FAIRFIELD,OH,39.3284,-84.5465,107.14.38.217 +US,BOERNE,TX,29.8239,-98.758,107.14.36.199 +DE,SULZBACH,HE,50.13,8.53,92.122.207.179 +CN,CHANGSHA,HN,28.20,112.97,72.246.191.19 +US,LONGBEACH,CA,33.7668,-118.1886,23.216.10.54 +US,SEARCY,AR,35.2662,-91.8491,96.16.7.101 +NL,AMSTERDAM,"",52.35,4.92,95.100.169.105 +US,HUNTINGTONBEACH,CA,33.7036,-117.9942,23.216.10.78 +CN,JINAN,SD,36.67,117.00,184.50.87.176 +CH,BERN,"",46.92,7.47,193.247.167.211 +US,BILLINGS,MT,45.6311,-108.3519,107.14.32.235 +CL,SANTIAGO,"",-33.45,-70.67,200.91.22.117 +DE,OLDENBURG,NI,53.17,8.20,92.122.207.179 +US,VISALIA,CA,36.2961,-119.382,96.17.12.44 +AU,HOBART,TAS,-42.92,147.33,210.9.88.72 +ET,ADISABEBA,"",9.03,38.70,80.239.237.231 +US,ROCKPORT,TX,28.0205,-97.0545,107.14.43.29 +HK,KOWLOON,"",22.32,114.18,23.76.205.90 +US,CHANDLER,AZ,33.3240,-111.8671,184.50.26.204 +CA,HAMILTON,ON,43.25,-79.83,72.246.43.233 +US,ANCHORAGE,AK,61.2169,-149.8682,165.254.1.206 +HK,HUNGHOM,"",22.30,114.18,23.76.205.111 +JP,NAKANO,14,35.57,139.28,72.246.184.89 +US,MOUNTDORA,FL,28.8027,-81.6446,63.148.206.235 +US,PISCATAWAY,NJ,40.5465,-74.4629,216.151.187.186 +US,LASVEGAS,NV,36.1730,-115.1233,23.61.195.163 +FR,MONTPELLIER,"",43.60,3.88,2.20.243.42 +US,SULLIVAN,MO,38.2643,-91.1348,63.216.54.216 +US,FAIROAKS,CA,38.6525,-121.2544,96.17.12.44 +US,RANCHOCUCAMONGA,CA,34.1370,-117.5982,23.216.10.54 +AF,KABUL,"",34.52,69.18,23.14.94.224 +TT,PORTOFSPAIN,"",10.65,-61.52,204.93.33.141 +DE,BREMEN,HB,53.08,8.80,194.25.95.225 +ZA,JOHANNESBURG,"",-26.20,28.08,41.193.163.53 +US,COACHELLA,CA,33.6820,-116.1678,184.50.26.194 +US,CHAMPAIGN,IL,40.1154,-88.2438,23.67.60.223 +FR,BAYONNE,"",43.48,-1.48,81.52.201.85 +PR,LUQUILLO,"",18.3744,-65.7168,72.246.65.26 +JP,YOKOHAMA,14,35.45,139.65,72.246.191.16 +FR,MARSEILLE,"",43.30,5.40,90.84.50.108 +AU,SUNSHINE,VIC,-37.78,144.83,184.84.221.85 +US,LIVERMORE,CA,37.6209,-121.6768,184.84.180.101 +US,PHILADELPHIA,PA,39.9525,-75.1644,23.67.242.139 +JM,KINGSTON,"",18.00,-76.80,165.254.205.7 +US,BEAVERTON,OR,45.4908,-122.8046,23.212.59.85 +US,ALHAMBRA,CA,34.0905,-118.1279,205.185.195.183 +US,PLEASANTHILL,CA,37.9547,-122.076,96.17.12.48 +US,CUPERTINO,CA,37.3086,-122.0891,96.17.12.44 +US,DAVIS,CA,38.5631,-121.7605,23.61.195.165 +CA,KAMLOOPS,BC,50.67,-120.33,184.27.179.187 +DE,HOYERSWERDA,SN,51.43,14.25,195.95.193.132 +DE,AACHEN,NW,50.77,6.10,80.157.170.158 +IT,PALERMO,"",38.12,13.37,79.140.80.222 +NL,ROTTERDAM,"",51.92,4.50,92.122.189.114 +IL,TELAVIV,"",32.07,34.77,212.25.69.134 +US,CORVALLIS,OR,44.6364,-123.2804,23.212.59.78 +HT,PORTAUPRINCE,"",18.54,-72.33,23.74.2.7 +NO,OSLO,"",59.92,10.75,2.21.240.40 +US,SOUTHFIELD,MI,42.4750,-83.2896,72.247.10.241 +PL,KRAKOW,"",50.08,19.92,88.221.93.150 +US,GILROY,CA,37.0418,-121.4684,23.216.10.54 +US,MINNEAPOLIS,MN,44.9847,-93.2709,23.67.60.223 +US,HICKSVILLE,NY,40.7626,-73.5241,184.26.44.42 +US,BELLEVUE,WA,47.6186,-122.204,23.212.59.85 +US,HYDEPARK,NY,41.8034,-73.8926,184.51.125.79 +SE,VAXJO,G,56.88,14.82,213.155.156.212 +US,LAKELAND,FL,28.0375,-81.9046,23.33.186.101 +US,DUBUQUE,IA,42.5490,-90.6988,23.77.234.35 +US,OAKLANDGARDENS,NY,40.7457,-73.7574,24.143.199.188 +ID,MULIA,"",-2.33,106.27,23.0.162.21 +US,DAVENPORT,IA,41.5221,-90.5751,107.14.38.217 +FR,NANCY,"",48.68,6.20,81.52.201.85 +AU,NORTHSYDNEY,NSW,-33.84,151.21,210.11.142.64 +US,AURORA,IL,41.7671,-88.2508,23.67.60.217 +DE,ERFURT,TH,50.98,11.03,80.157.150.201 +US,APOPKA,FL,28.6645,-81.5402,23.33.186.101 +US,WOODBURY,NJ,39.8266,-75.1276,184.26.44.42 +CA,FREDERICTON,NB,45.95,-66.63,2.20.142.166 +GR,THESSALONIKI,"",40.63,22.93,2.16.217.206 +US,ATHENS,OH,39.3095,-82.081,107.14.38.217 +US,CHESTERTOWN,MD,39.2007,-76.1457,168.143.243.37 +GT,GUATEMALACITY,"",14.63,-90.52,72.246.65.38 +US,PURCHASE,NY,41.0397,-73.7118,69.31.77.208 +US,TRACY,CA,37.7546,-121.3694,23.61.195.163 +US,HEWITT,TX,31.4546,-97.1957,184.26.93.116 +US,LUFKIN,TX,31.3301,-94.744,64.86.135.210 +AT,VIENNA,"",48.20,16.37,195.145.147.108 +US,PLEASANTON,CA,37.6395,-121.8586,23.215.15.22 +US,ELKO,NV,40.8858,-115.7034,23.74.8.8 +US,ARLINGTON,TX,32.6288,-97.1183,184.28.23.4 +US,VICTORVILLE,CA,34.5003,-117.3379,23.216.10.54 +US,FULLERTON,CA,33.8793,-117.8962,184.50.26.179 +US,FORTSMITH,AR,35.3642,-94.4158,23.215.15.22 +PR,AGUADILLA,"",18.4409,-67.1508,23.33.186.101 +US,TEMPLECITY,CA,34.1016,-118.0554,23.216.10.54 +FR,CHAUMONT,"",49.27,1.88,2.16.117.200 +US,WAUKEGAN,IL,42.3639,-87.8447,23.212.53.64 +US,SUNCITY,AZ,33.6050,-112.2837,184.50.26.179 +US,CUMMING,GA,34.2093,-84.1423,72.246.247.5 +US,INDIO,CA,33.7269,-116.2361,184.50.26.179 +US,BAKERSFIELD,CA,35.3841,-119.0207,184.26.93.111 +US,MALIBU,CA,34.0402,-118.6328,173.223.52.70 +DE,BADEN,BW,48.75,8.25,2.16.217.206 +US,RUCKERSVILLE,VA,38.2469,-78.3926,184.26.44.42 +CN,HANGZHOU,ZJ,30.26,120.17,23.76.205.90 +US,BOSSIERCITY,LA,32.5785,-93.6897,23.5.164.146 +DE,HANNOVER,NI,52.37,9.72,80.157.170.154 +US,DENISON,TX,33.7390,-96.5197,23.215.15.22 +US,CLIFTON,NJ,40.8800,-74.1446,184.26.44.42 +US,HONOLULU,HI,21.3069,-157.8584,23.212.53.75 +US,LODI,CA,38.1161,-121.1069,23.212.52.79 +CA,SASKATOON,SK,52.13,-106.67,205.185.195.183 +US,TUSCALOOSA,AL,33.1664,-87.6118,205.185.205.102 +US,MOBILE,AL,30.6945,-88.0431,65.120.60.228 +IN,SURAT,GJ,21.17,72.83,23.57.69.156 +US,SAINTMARYS,GA,30.7777,-81.5701,184.51.35.215 +DE,GOTTINGEN,NI,51.53,9.93,194.25.95.225 +US,AUGUSTA,GA,33.4341,-81.956,23.79.240.36 +US,SANMARCOS,CA,33.1507,-117.1748,184.50.26.204 +SE,ARJEPLOG,BD,66.05,17.90,213.155.156.212 +GB,MILTONKEYNES,EN,52.03,-0.70,92.122.54.12 +JP,NIHONBASHIGOFUKUBASHI,13,35.68,139.77,23.61.250.113 +US,NORTHHILLS,CA,34.2386,-118.4807,184.50.26.194 +US,MESA,AZ,33.4340,-111.8483,63.226.34.173 +TR,ISTANBUL,"",41.02,28.96,2.16.217.211 +US,WILBURTON,OK,34.8806,-95.3086,23.215.15.9 +DE,SAARBRUCKEN,SL,49.23,7.00,194.25.95.212 +RO,ALBAIULIA,"",45.07,28.53,88.221.93.150 +US,WESTCOVINA,CA,34.0668,-117.9376,23.216.10.54 +IN,ROHTAK,HR,28.90,76.57,124.124.252.153 +PK,KARACHI,"",24.87,67.05,23.5.165.167 +IN,HARYANA,HR,29.62,76.98,96.17.182.136 +AU,ROSEDALE,VIC,-38.15,146.78,23.62.157.32 +MY,SHAHALAM,"",3.08,101.53,23.198.99.130 +US,HOLLYWOOD,FL,26.0478,-80.1254,23.79.240.36 +US,ALTON,IL,38.9395,-90.1236,96.17.14.16 +BG,SEVLIEVO,"",43.02,25.10,2.20.45.102 +PH,QUEZONCITY,"",14.63,121.03,202.78.83.170 +GB,ILFORD,EN,51.55,0.05,23.3.15.22 +US,HUNTINGTON,WV,38.3693,-82.4123,184.26.44.42 +US,CARLSBAD,CA,33.1500,-117.3007,184.50.26.189 +US,GARNER,NC,35.6418,-78.5748,96.16.12.216 +RU,URAL,"",54.11,38.33,213.155.156.208 +RU,VOLGOGRAD,"",48.80,44.59,80.239.217.238 +AU,NORTHRYDE,NSW,-33.82,151.10,23.62.224.60 +US,NEWLENOX,IL,41.5052,-87.9609,23.74.8.24 +US,VENICE,CA,33.9944,-118.4634,184.27.45.150 +US,STOCKTON,CA,37.9578,-121.2897,96.17.12.44 +US,AZUSA,CA,34.1312,-117.9157,23.216.10.78 +US,ESCONDIDO,CA,33.0829,-117.0241,23.216.10.54 +MT,VALLETTA,"",35.90,14.51,77.67.29.109 +KR,YONGDONG,"",36.92,126.98,23.65.188.30 +US,BRONX,NY,40.8208,-73.9235,184.51.125.79 +IN,ANDRA,AP,18.35,83.20,80.239.237.231 +CN,WUHAN,HB,30.58,114.27,117.103.188.218 +CA,PARKSVILLE,BC,49.30,-124.32,184.27.179.181 +DE,PADERBORN,NW,51.72,8.77,195.145.147.101 +GB,LEICESTER,EN,52.63,-1.13,184.27.139.24 +JP,OTEMACHI,13,35.68,139.77,72.246.191.19 +US,ROSAMOND,CA,34.8931,-118.3533,23.216.10.78 +US,EUGENE,OR,44.0685,-123.082,206.104.149.133 +US,SNOQUALMIE,WA,47.5717,-121.7785,206.104.149.146 +CN,HEFEI,AH,31.86,117.28,72.246.191.19 +IN,NAGORE,TN,10.82,79.85,117.239.240.96 +US,ROSWELL,NM,33.4293,-104.519,65.116.149.89 +DE,GOERLITZ,SN,51.17,15.00,195.95.193.147 +US,WAUPACA,WI,44.3534,-89.1229,23.63.227.227 +US,MURFREESBORO,TN,35.7571,-86.3959,23.79.240.36 +IN,PUNE,MH,18.53,73.87,23.57.69.159 +IQ,BAGHDAD,"",33.34,44.39,195.27.155.188 +QA,DOHA,"",25.29,51.53,82.148.111.135 +US,JERSEYCITY,NJ,40.7286,-74.0775,23.61.195.165 +US,LITTLEROCK,AR,34.7467,-92.2799,184.84.180.101 +US,EVERGREEN,AL,31.4945,-86.9123,184.51.35.226 +US,DANVILLE,VA,36.6603,-79.4863,184.27.45.150 +FR,PUTEAUX,"",48.87,2.23,23.200.87.59 +US,YUBACITY,CA,39.0204,-121.6141,23.212.52.88 +TR,KOCA,"",41.68,32.48,92.122.215.67 +US,BALDWINPARK,CA,34.0941,-117.9709,184.27.45.150 +US,SANTAMONICA,CA,34.0153,-118.4926,23.216.10.78 +US,MARION,MA,41.7087,-70.7664,184.25.109.213 +CN,CHENGDU,SC,30.67,104.07,72.246.191.16 +US,LAWNDALE,CA,33.8885,-118.3514,184.50.26.204 +US,MEAD,CO,40.2553,-104.9897,23.215.15.9 +US,BLYTHE,CA,33.5664,-114.6283,24.143.194.216 +US,LINCOLN,NE,40.8000,-96.6664,184.26.93.116 +US,ANTIOCH,CA,37.9799,-121.8022,23.212.52.79 +AT,AINET,"",46.87,12.70,23.62.237.133 +KZ,ASTANA,"",51.17,71.50,80.239.222.167 +US,BIGRAPIDS,MI,43.6800,-85.5606,23.63.227.214 +HR,ZAGREB,"",45.80,16.00,23.14.94.220 +US,BRIGHAMCITY,UT,41.4833,-112.0954,184.84.180.98 +GB,KNOWSLEY,EN,53.45,-2.85,88.221.87.112 +FI,SAUNALAHTI,"",63.22,28.55,193.184.164.239 +NZ,PORIRUA,"",-41.13,174.85,219.88.186.172 +PH,MANILA,"",14.58,121.00,202.78.83.170 +DE,DORTMUND,NW,51.52,7.45,80.157.170.158 +US,ELKCITY,OK,35.4257,-99.4694,23.215.15.32 +US,MEMPHIS,TN,35.1496,-90.0487,23.220.100.224 +US,WINTERPARK,FL,28.5987,-81.3537,209.170.117.178 +US,NEWORLEANS,LA,29.9574,-90.0769,23.215.15.22 +US,CATHEDRALCITY,CA,33.8234,-116.4603,184.50.26.194 +FR,ROUEN,"",49.43,1.08,2.20.243.45 +US,PALMCOAST,FL,29.4748,-81.1274,23.33.186.101 +CH,BIEL,"",47.17,7.25,193.247.167.214 +UA,ODESA,"",46.47,30.73,80.239.149.123 +US,ELKGROVEVILLAGE,IL,42.0131,-87.9972,23.220.148.122 +US,RICHARDSON,TX,32.9743,-96.7425,107.14.36.200 +US,COCOABEACH,FL,28.3302,-80.6145,23.33.186.134 +US,SANTABARBARA,CA,34.4179,-119.711,184.50.26.204 +US,SHERWOOD,OR,45.3505,-122.8661,184.27.179.181 +US,HAYWARD,CA,37.6687,-122.0799,23.212.52.82 +CN,GUIYANG,GZ,26.58,106.72,23.76.205.111 +RU,NOVOSIBIRSK,"",55.03,82.92,2.21.240.61 +US,CLOVIS,CA,36.8770,-119.5829,96.17.12.48 +MX,HERMOSILLO,SON,29.07,-110.97,173.223.52.67 +US,LAKEHAVASUCITY,AZ,34.6022,-113.772,24.143.194.180 +US,DOWNEY,CA,33.9400,-118.1319,184.50.26.179 +US,MANSFIELD,OH,40.7584,-82.5156,205.185.195.170 +MV,MALE,"",4.17,73.50,96.17.182.136 +US,MURRIETA,CA,33.5484,-117.2689,23.216.10.54 +US,IRMO,SC,34.1400,-81.2028,72.246.247.5 +US,COSTAMESA,CA,33.6791,-117.9087,184.50.26.201 +US,TOMBALL,TX,30.0721,-95.6453,96.17.163.165 +US,BELLINGHAM,WA,48.7531,-122.5024,184.27.179.179 +US,GARDENA,CA,33.8912,-118.2972,184.50.26.201 +DE,KOBLENZ,RP,50.35,7.60,194.25.95.212 +US,KIRKSVILLE,MO,40.1490,-92.6667,107.14.43.30 +US,WICHITAFALLS,TX,33.9834,-98.4403,184.28.23.24 +JP,HODOGAYA,14,35.45,139.60,117.104.139.162 +HR,SPLIT,"",43.51,16.46,46.33.70.97 +US,TURLOCK,CA,37.4741,-120.8695,23.216.10.54 +CA,ETOBICOKE,ON,43.70,-79.57,209.148.192.57 +US,JOLIET,IL,41.5083,-88.2276,23.67.60.223 +US,SOUTHJORDAN,UT,40.5586,-111.9523,23.215.15.32 +US,TUJUNGA,CA,34.3190,-118.2411,184.50.26.179 +FR,AUBERVILLIERS,"",48.92,2.38,2.20.243.42 +FI,HELSINKI,"",60.18,24.93,80.239.237.84 +US,OCEANSIDE,CA,33.1959,-117.3789,63.233.112.196 +US,CASTAIC,CA,34.4864,-118.5786,184.50.26.204 +US,GROTON,CT,41.3595,-72.0439,72.247.10.237 +US,COLLINSVILLE,IL,38.6902,-89.9816,96.17.14.16 +US,ALBUQUERQUE,NM,35.0846,-106.6516,184.84.180.101 +MX,CIUDADJUAREZ,CHH,19.07,-103.88,23.215.15.22 +US,WOODBRIDGE,VA,38.6245,-77.2692,184.28.17.55 +US,VEROBEACH,FL,27.6406,-80.4018,184.28.184.16 +US,HIGHLAND,CA,34.1353,-117.1532,23.216.10.78 +ES,BARCELONA,"",41.38,2.18,213.248.113.93 +US,HARTSELLE,AL,34.4480,-86.8894,23.220.100.223 +EG,CAIRO,"",30.05,31.25,79.140.94.243 +US,BIGSTONEGAP,VA,36.8453,-82.7571,23.212.53.64 +US,WALNUTCREEK,CA,37.8720,-122.0686,23.212.52.82 +CA,KELOWNA,BC,49.90,-119.48,184.27.179.187 +US,THOMASTON,GA,32.8808,-84.3396,23.79.240.36 +DE,MEERBUSCH,NW,51.28,6.67,2.22.61.102 +NO,FORNEBU,"",59.90,10.63,2.21.240.40 +FR,STRASBOURG,"",48.58,7.75,77.67.27.231 +US,ANNARBOR,MI,42.2601,-83.8448,23.63.227.214 +US,ALLEN,TX,33.0968,-96.6341,96.16.7.120 +US,COVINGTON,LA,30.4598,-90.1271,96.17.153.157 +SE,UPPSALA,C,59.85,17.63,80.239.237.93 +MX,MONTERREY,NLE,25.67,-100.32,23.215.15.22 +US,ORANGE,CA,33.7878,-117.8523,184.50.26.179 +JP,SOKA,11,35.82,139.81,117.104.139.136 +GU,HAGATNA,"",13.4744,144.7478,64.145.95.145 +US,BOSTON,MA,42.3581,-71.0647,23.67.244.224 +US,REDONDOBEACH,CA,33.8305,-118.3842,184.50.26.192 +AU,BURNIE,TAS,-41.07,145.92,202.7.177.76 +US,MAMMOTHLAKES,CA,37.6599,-118.912,23.216.10.54 +US,KENNEWICK,WA,46.2117,-119.1733,23.61.195.165 +DE,CHEMNITZ,SN,50.83,12.92,194.25.95.214 +AD,ANDORRA,"",42.50,1.52,80.149.168.114 +US,SANFORD,FL,28.8131,-81.3279,23.34.56.142 +US,LAKEVILLE,CT,41.9547,-73.4419,165.254.202.92 +US,AKRON,OH,41.0433,-81.5239,107.14.38.218 +AU,FERNTREEGULLY,VIC,-37.88,145.30,184.84.221.116 +US,AUDUBON,NJ,39.8910,-75.0738,23.67.60.223 +DE,NURNBERG,BY,49.45,11.07,195.145.147.108 +US,EAUCLAIRE,WI,44.7381,-91.5038,184.85.215.165 +US,CONWAY,AR,35.0822,-92.366,96.16.7.120 +US,EASTSYRACUSE,NY,43.1073,-76.0418,107.14.38.218 +US,OZONEPARK,NY,40.6844,-73.8499,184.26.44.42 +FR,VILLARDBONNOT,"",45.23,5.88,2.16.117.200 +US,COLUMBUS,OH,40.0994,-83.0166,107.14.38.217 +US,PLATTEVILLE,WI,42.7466,-90.4931,63.151.29.15 +US,WAKEFOREST,NC,35.9666,-78.5355,209.18.41.27 +NZ,WELLINGTON,"",-41.30,174.78,219.88.186.167 +HR,CORE,"",45.09,16.33,23.14.94.228 +KH,PHNOMPENH,"",11.55,104.92,23.76.205.111 +US,SAHUARITA,AZ,31.9776,-110.9216,23.215.15.22 +JP,HAMAMATSU,22,34.70,137.73,117.104.138.235 +US,LIVINGSTON,NJ,40.7857,-74.3293,23.67.242.156 +US,HEMET,CA,33.6979,-116.9786,184.27.45.157 +US,PUEBLO,CO,38.2964,-104.5387,184.84.180.68 +US,ELMONTE,CA,34.0769,-118.0327,184.50.26.201 +US,CHESTERFIELD,MO,38.6405,-90.6464,63.216.54.216 +GB,UDDINGSTON,SC,55.80,-4.07,88.221.87.94 +US,BABYLON,NY,40.6311,-73.3431,184.26.44.38 +DE,KASSEL,HE,51.32,9.50,194.25.95.225 +US,GRANADAHILLS,CA,34.2913,-118.506,184.27.45.157 +DE,DREIEICH,HE,50.00,8.70,92.122.215.89 +US,MANTECA,CA,37.8341,-121.2013,23.212.52.79 +PL,KATOWICE,"",50.27,19.02,95.101.2.112 +US,MCKEE,KY,37.4446,-84.0227,23.63.227.227 +US,WESTWARWICK,RI,41.7000,-71.516,72.247.10.241 +US,ENDICOTT,NY,42.1332,-76.0798,107.14.38.227 +ID,DENPASAR,"",-8.65,115.22,23.0.162.46 +RU,VOLOGDA,"",59.22,39.90,2.21.240.40 +US,MIDLOTHIAN,VA,37.4373,-77.6622,63.130.161.140 +US,BRECKSVILLE,OH,41.3049,-81.6177,96.17.9.14 +US,AMHERST,MA,42.3773,-72.4671,165.254.35.197 +US,SANLUISOBISPO,CA,35.2383,-120.6214,23.216.10.78 +US,NEWHOLLAND,PA,40.1038,-76.0725,184.27.45.150 +US,GILBERT,AZ,33.3504,-111.8085,184.50.26.203 +US,SYOSSET,NY,40.8243,-73.4974,165.254.35.182 +US,PACIFICA,CA,37.6009,-122.4839,173.223.52.70 +RU,AKTAY,"",55.82,46.78,92.122.215.67 +US,AUBREY,TX,33.2863,-96.9901,184.28.23.24 +US,ROMA,TX,26.5818,-98.985,184.26.93.116 +US,FORTMYERS,FL,26.6175,-81.8713,23.79.240.36 +US,WINSTONSALEM,NC,36.1131,-80.1983,184.27.45.157 +US,BUCKEYE,AZ,33.2239,-112.8563,184.50.26.203 +US,MIDDLETOWN,PA,40.1873,-76.6948,23.192.161.21 +US,BOWIE,MD,38.9862,-76.7389,23.192.161.21 +DE,NETZE,HE,51.22,9.10,23.14.94.224 +UA,DNIPROPETROVSK,"",48.45,34.98,23.14.94.224 +MY,SEMENYIH,"",2.95,101.85,203.106.85.195 +US,GAITHERSBURG,MD,39.1382,-77.1868,184.27.45.157 +US,MISSIONVIEJO,CA,33.6002,-117.6711,2.20.142.166 +US,CENTERVILLE,IA,40.7100,-92.9234,63.216.54.229 +US,MONEE,IL,41.4121,-87.7808,23.67.60.220 +US,CLINTON,MD,38.7501,-76.9068,184.27.45.150 +TR,IZMIR,"",38.42,27.15,193.45.15.198 +KZ,ATYRAU,"",47.12,51.88,23.14.94.228 +US,BINGHAMTON,NY,42.1934,-75.8849,107.14.38.227 +DE,HOST,NW,51.65,6.18,92.122.215.89 +US,PORTOLAVALLEY,CA,37.3686,-122.2154,184.85.249.6 +RU,ROSTOVONDON,"",47.24,39.71,2.21.240.40 +US,PARKER,CO,39.5027,-104.7087,184.84.180.101 +US,HOLLISTER,CA,36.7975,-121.2316,96.17.12.44 +CN,WENZHOU,ZJ,28.02,120.65,72.246.191.19 +US,ANAHEIM,CA,33.8444,-117.9519,184.50.26.179 +US,CASTROVALLEY,CA,37.7052,-122.0821,23.212.52.79 +US,BERKELEY,CA,37.8718,-122.2718,23.61.195.163 +US,KATY,TX,29.8394,-95.7377,23.212.53.64 +IR,GOSTAR,"",35.47,48.88,23.215.60.48 +RU,NOVGOROD,"",58.52,31.28,213.155.156.208 +US,BLACKSBURG,VA,37.2556,-80.429,65.121.209.133 +RU,KRASNODAR,"",45.03,38.98,2.21.240.40 +LT,PANEVEZYS,"",55.73,24.35,92.122.189.114 +GB,SOUTHBANK,EN,54.57,-1.15,173.222.211.203 +US,WELLSBORO,PA,41.7308,-77.349,184.27.45.157 +US,RIVERDALE,GA,33.5562,-84.3998,72.246.247.5 +VN,HOCHIMINHCITY,"",10.75,106.67,23.5.165.168 +US,HERNDON,VA,38.9807,-77.3799,184.27.45.157 +US,INGLEWOOD,CA,33.9563,-118.3585,184.50.26.194 +US,PICKERINGTON,OH,39.9019,-82.7452,96.17.9.8 +US,GRENADA,MS,33.8096,-89.8042,96.17.153.162 +US,RANCHOSANTAMARGARITA,CA,33.6340,-117.6061,23.215.15.22 +SV,SANSALVADOR,"",13.70,-89.20,72.246.65.23 +CZ,PRAGUE,"",50.08,14.47,23.62.237.138 +IM,DOUGLAS,"",54.15,-4.48,195.245.125.249 +FR,NANTES,"",47.22,-1.55,81.52.201.101 +US,BLYTHEVILLE,AR,35.9221,-89.9037,65.113.249.11 +RO,GHEORGHENI,"",46.72,25.62,88.221.93.150 +US,CORONA,CA,33.8754,-117.5659,165.254.51.142 +TZ,ARUSHA,"",-3.37,36.68,41.193.163.45 +JP,KYOWA,01,43.82,144.02,72.246.184.81 +US,MENDOTA,MN,44.8871,-93.1617,63.151.29.15 +US,ALSIP,IL,41.6719,-87.7294,23.67.60.223 +US,SPARTANBURG,SC,34.9341,-82.0149,23.79.240.36 +US,CANTON,GA,34.2348,-84.4442,63.216.54.229 +MY,CYBERJAYA,"",2.97,101.58,23.15.10.91 +US,MORRISTOWN,TN,36.1752,-83.2659,64.86.201.118 +US,MONSON,MA,42.0890,-72.3226,184.25.109.200 +BA,SRPSKA,"",44.81,18.30,23.62.237.133 +US,TRENTON,NJ,40.2167,-74.7433,184.26.44.42 +RO,BUCHAREST,"",44.43,26.10,92.122.215.67 +US,WHITTIER,CA,34.0076,-118.0335,23.216.10.78 +US,MADISONVILLE,KY,37.3245,-87.464,107.14.38.227 +US,AZLE,TX,32.9120,-97.556,23.215.15.22 +IN,BHIWANDI,MH,19.30,73.07,23.57.69.159 +US,BRENTWOOD,TN,36.0347,-86.7836,23.220.100.224 +US,LORAIN,OH,41.4482,-82.1803,107.14.38.227 +US,PINOLE,CA,37.9896,-122.2692,23.61.195.166 +AT,GRAZ,"",47.07,15.45,195.145.147.108 +ID,TANGERANG,"",-6.18,106.62,23.0.162.46 +US,HUMBLE,TX,29.9987,-95.2618,23.212.53.75 +US,ATLANTICBEACH,FL,30.3485,-81.4173,23.79.240.37 +US,BRIDGEPORT,CT,41.1667,-73.2054,184.51.125.79 +US,WARRIOR,AL,33.8170,-86.8457,23.220.100.224 +SE,MALMO,M,55.60,13.00,213.155.156.206 +DE,KAISERSLAUTERN,RP,49.45,7.75,194.25.95.212 +US,FALLBROOK,CA,33.3988,-117.2649,165.254.138.165 +US,IDAHOFALLS,ID,43.4980,-111.7302,192.80.13.117 +SE,LILJEHOLMEN,AB,59.32,18.02,213.155.156.207 +FR,BERGERAC,"",44.85,0.48,92.122.189.114 +US,SMITHTOWN,NY,40.8527,-73.2109,23.67.242.139 +US,PALMSPRINGS,CA,33.8563,-116.5712,184.50.26.194 +DE,BAMBERG,BY,49.87,10.87,194.25.95.214 +AU,ROCHEDALE,QLD,-27.57,153.13,104.72.70.95 +RU,ROSTOV,"",57.19,39.42,217.212.227.31 +US,RAINSVILLE,AL,34.5004,-85.8413,64.86.201.121 +HK,KWUNTONG,"",22.32,114.22,23.76.205.111 +US,SANANGELO,TX,31.5873,-100.522,23.5.164.146 +HK,KWAICHUNG,"",22.35,114.13,23.76.205.90 +US,VIDOR,TX,30.1707,-94.0082,107.14.43.30 +US,GRANDPRAIRIE,TX,32.7740,-97.0052,184.26.93.111 +US,GREATFALLS,MT,47.5115,-111.2723,184.27.179.181 +US,PERRIS,CA,33.7921,-117.3085,184.50.26.201 +US,PLACENTIA,CA,33.8804,-117.8555,23.220.149.114 +US,CHINOHILLS,CA,33.9508,-117.7322,23.216.10.78 +US,MONTGOMERY,AL,32.3667,-86.3002,23.79.240.37 +MX,TIJUANA,BCN,32.53,-117.02,165.254.144.32 +US,FLUSHING,NY,40.7553,-73.8268,24.143.199.188 +VE,CARACAS,"",10.50,-66.92,72.246.65.37 +US,FREDERICK,MD,39.4393,-77.3428,23.192.161.16 +US,WESTPLAINS,MO,36.7256,-91.9123,107.14.38.218 +US,PIOCHE,NV,38.2635,-114.484,23.216.10.78 +US,LEAGUECITY,TX,29.4885,-95.1021,23.212.53.75 +CN,ZHENGZHOU,HA,34.76,113.65,23.76.205.90 +DE,NORDERSTEDT,SH,53.70,10.02,92.122.207.164 +US,LIVONIA,MI,42.3684,-83.3717,69.22.154.219 +US,PORTORANGE,FL,29.2107,-81.0232,184.51.145.22 +US,ROGERS,AR,36.3725,-94.0691,23.215.15.32 +DE,SAARLOUIS,SL,49.32,6.75,2.20.142.166 +BE,ANTWERP,"",51.22,4.42,23.62.100.152 +US,BURBANK,CA,34.2040,-118.3029,184.50.26.201 +CN,SHANGHAI,SH,31.22,121.46,184.50.87.176 +US,MIDLAND,MI,43.5802,-84.3509,23.63.227.214 +US,ONEIDA,NY,43.0606,-75.6518,107.14.38.227 +US,ROYALOAK,MI,42.4907,-83.1379,69.22.154.215 +US,ROANOKE,TX,32.9960,-97.2275,184.28.23.4 +PE,LIMA,"",-12.05,-77.05,200.60.190.82 +US,WESTLAKEVILLAGE,CA,34.1707,-118.8364,184.50.26.203 +CA,WINNIPEG,MB,49.88,-97.17,23.74.8.24 +US,SAINTPAUL,MN,44.9661,-93.0837,63.151.29.12 +US,BUENAPARK,CA,33.8459,-118.0114,107.14.44.212 +US,COLTON,CA,34.0027,-117.2405,184.87.195.99 +GB,ACTON,EN,51.50,-0.25,23.67.255.158 +DE,ROLAND,NW,51.77,8.00,95.101.2.122 +PK,ISLAMABAD,"",33.70,73.17,79.140.94.234 +US,CAMARILLO,CA,34.2276,-119.0699,23.61.195.163 +US,MARYSVILLE,WA,48.0544,-122.1499,184.84.180.98 +RU,PETROZAVODSK,"",61.82,34.33,2.21.240.61 +US,SANLEANDRO,CA,37.7164,-122.1648,96.17.12.44 +US,WALDORF,MD,38.6041,-76.8335,23.192.161.16 +US,NANUET,NY,41.0984,-74.0095,184.26.44.40 +DE,MANNHEIM,BW,49.49,8.46,80.239.237.231 +US,SAINTJAMES,NY,40.8903,-73.169,184.26.44.42 +US,SANBRUNO,CA,37.6225,-122.4186,216.246.93.44 +DE,FREIBURG,BW,48.00,7.85,80.157.150.201 +GR,IRAKLEIO,"",35.33,25.13,23.14.94.220 +FR,GIGNY,"",48.60,4.57,2.16.117.200 +DE,BREMERHAVEN,HB,53.55,8.58,80.157.150.197 +US,NORTHBERGEN,NJ,40.7933,-74.0263,184.51.125.79 +DE,KREFELD,NW,51.33,6.57,80.157.170.154 +US,PLACERVILLE,CA,38.7308,-120.774,23.212.52.88 +US,PROVIDENCE,RI,41.8238,-71.4133,165.254.35.197 +US,NORTHBRUNSWICK,NJ,40.4497,-74.482,184.51.125.68 +US,CARSON,CA,33.8231,-118.267,184.50.26.194 +US,SECAUCUS,NJ,40.7808,-74.0651,204.94.155.231 +US,CINCINNATI,OH,39.1616,-84.4569,23.74.8.8 +US,PORTSMOUTH,VA,36.8107,-76.3702,23.220.148.108 +US,SPRING,TX,30.0613,-95.3841,23.212.53.75 +CY,NICOSIA,"",35.17,33.37,92.122.215.89 +US,ELKRIDGE,MD,39.0285,-76.7125,184.28.17.76 +US,KISSIMMEE,FL,28.3074,-81.4274,23.34.56.142 +US,BATTLECREEK,MI,42.3247,-85.0949,23.67.60.223 +US,FORTLAUDERDALE,FL,26.1210,-80.1281,23.79.240.36 +US,WESTLAFAYETTE,IN,40.4858,-86.9802,23.63.227.214 +CA,CHATHAM,ON,42.40,-82.18,72.246.43.215 +DE,SINGEN,BW,48.97,8.57,2.16.217.211 +CN,NANJING,JS,32.06,118.78,117.103.188.218 +US,EVANSTON,IL,42.0566,-87.6974,107.14.38.217 +US,LANDER,WY,42.6143,-108.5863,23.63.227.214 +US,MICHIGANCITY,IN,41.6870,-86.8677,23.67.60.220 +US,FAYETTEVILLE,AR,35.9902,-94.083,23.77.234.35 +RU,SERPUKHOV,"",54.92,37.41,2.21.240.61 +US,WESTRICHLAND,WA,46.3012,-119.3697,184.27.179.159 +RU,YOSHKAROLA,"",56.64,47.87,80.239.237.80 +RU,SETI,"",53.36,34.21,217.212.227.25 +US,INDIANA,PA,40.6222,-79.1593,184.28.17.55 +US,LAWTON,OK,34.5483,-98.2849,184.28.23.4 +US,MIAMIBEACH,FL,25.7928,-80.3138,165.254.205.13 +CA,VICTORIA,BC,48.43,-123.35,165.254.35.197 +US,HENDERSONVILLE,NC,35.2687,-82.5413,184.51.35.226 +FR,LADEFENSE,"",48.90,2.23,90.84.50.204 +DE,BOCHUM,NW,51.48,7.22,194.25.95.219 +DO,SANTODOMINGO,"",18.47,-69.90,72.246.65.38 +US,MILLINGTON,MI,43.2680,-83.543,23.74.8.24 +US,LASALLE,IL,41.3955,-89.0957,23.67.60.223 +PL,POZNAN,"",52.42,16.97,2.22.52.105 +AU,THOMASTOWN,VIC,-37.68,145.02,23.62.8.21 +US,FRANKFORT,IL,41.4748,-87.8351,23.67.60.222 +BA,MOSTAR,"",43.34,17.81,77.67.29.109 +US,OKLAHOMACITY,OK,35.4678,-97.5164,23.215.15.22 +US,HAWTHORNE,CA,33.9143,-118.3494,184.87.195.99 +US,OLATHE,KS,38.8815,-94.8187,23.67.60.222 +SA,JEDDAH,"",21.52,39.22,79.140.94.234 +US,BURLESON,TX,32.5215,-97.3032,96.16.7.120 +US,PANORAMACITY,CA,34.2243,-118.4446,184.50.26.179 +US,WADSWORTH,OH,41.0524,-81.7404,184.27.45.157 +DE,ULM,BW,48.40,10.00,80.157.150.192 +JP,MORIOKA,03,39.70,141.15,96.7.251.97 +US,NAPLES,FL,26.1418,-81.795,23.79.240.37 +CN,TIANJIN,TJ,39.14,117.18,184.50.87.178 +US,WESTJORDAN,UT,40.6225,-111.9765,184.84.180.68 +US,KELLER,TX,32.9347,-97.2515,23.5.164.146 +US,GRESHAM,OR,45.5092,-122.431,23.212.59.63 +US,FALLSCHURCH,VA,38.8669,-77.1528,23.220.148.108 +US,STERLING,MI,44.0665,-84.046,23.67.60.217 +US,ENGLEWOOD,CO,39.6440,-104.9826,184.84.180.92 +US,GENEVA,NY,42.8475,-77.0198,107.14.38.224 +US,PALMBAY,FL,28.0264,-80.6045,23.33.186.134 +US,WESTFIELD,MA,42.1558,-72.7734,23.74.8.24 +US,PICORIVERA,CA,33.9895,-118.0913,184.50.26.201 +US,CHAMBERSBURG,PA,39.9438,-77.6827,23.192.161.16 +US,RUSTON,LA,32.5075,-92.6828,23.5.164.146 +US,WALLINGFORD,PA,39.8901,-75.3702,184.26.44.42 +US,REDLANDS,CA,34.0057,-117.1506,184.50.26.201 +US,WENATCHEE,WA,47.3635,-120.3481,184.27.179.187 +US,WILLITS,CA,39.4525,-123.3878,184.84.180.98 +CA,KITCHENER,ON,43.45,-80.50,72.246.43.233 +US,RIALTO,CA,34.1109,-117.3774,184.87.195.109 +JP,SHIZUOKA,22,34.97,138.38,72.246.191.16 +US,MARYVILLE,TN,35.7829,-83.8797,184.28.127.55 +US,SEASIDE,CA,36.6221,-121.8217,96.17.12.44 +IN,ANANDNAGAR,UP,27.10,83.28,124.124.252.153 +US,WASILLA,AK,61.5827,-149.4056,96.17.108.26 +US,VANNUYS,CA,34.1781,-118.4316,107.14.44.185 +RU,VLADIKAVKAZ,"",43.04,44.68,96.7.251.95 +MC,MONACO,"",43.73,7.42,2.22.49.28 +US,MCMINNVILLE,OR,45.1977,-123.2704,184.27.179.159 +GB,SOUTHAMPTON,EN,50.90,-1.40,184.27.45.157 +CN,CHANGCHUN,JL,43.89,125.32,72.246.190.189 +RU,KRASNOYARSK,"",56.01,92.79,2.21.240.61 +DE,GIESSEN,HE,50.58,8.65,194.25.95.214 +US,ELCAJON,CA,32.7856,-116.8874,184.50.26.204 +US,WINDSOR,CO,40.4952,-104.8788,173.197.194.159 +US,AUBURNHILLS,MI,42.6398,-83.2944,23.67.60.223 +US,JUSTICE,IL,41.7509,-87.8345,23.67.60.223 +US,IRVING,TX,32.8139,-96.9488,23.215.15.32 +GU,TAMUNING,"",13.4839,144.7769,165.254.96.242 +ZA,DURBAN,"",-29.85,31.02,195.245.125.249 +US,CRANBURY,NJ,40.3132,-74.5206,23.67.60.222 +US,GRANDRAPIDS,MI,42.9634,-85.6681,23.67.60.223 +US,RAYMORE,MO,38.7996,-94.4429,23.67.60.222 +US,PLANO,TX,33.0562,-96.7336,107.14.36.200 +US,EASTLANSING,MI,42.7547,-84.4613,165.254.207.111 +BH,ALMANAMAH,"",26.24,50.58,2.20.249.5 +US,WHITEMARSH,MD,39.3909,-76.4042,23.192.161.21 +US,PADUCAH,KY,37.0331,-88.716,23.220.100.223 +DE,BONN,NW,50.73,7.10,92.122.215.67 +IN,AHMADABAD,GJ,23.03,72.62,96.17.182.136 +US,NEWPORTNEWS,VA,37.0588,-76.4641,96.6.47.120 +US,TERREHAUTE,IN,39.4668,-87.4112,107.14.38.217 +US,PERRYTON,TX,36.2791,-100.8094,23.74.8.24 +US,GONZALES,LA,30.2383,-90.9202,23.215.15.22 +US,POTTSVILLE,PA,40.6882,-76.264,23.67.242.156 +US,PARKERSBURG,WV,39.2786,-81.5101,96.17.9.14 +US,FLINT,MI,43.0125,-83.6878,23.67.60.220 +US,LITHONIA,GA,33.6707,-84.1416,72.246.247.5 +NZ,PARADISE,"",-44.73,168.37,184.28.126.7 +US,ENTERPRISE,AL,31.4127,-85.8669,184.26.93.116 +US,SAINTPETERS,MO,38.8003,-90.6176,204.93.47.220 +US,PRINCETON,WV,37.3649,-81.0293,184.28.17.76 +OM,MASQAT,"",23.61,58.59,23.57.69.159 +JP,KOBE,28,34.68,135.17,117.104.139.136 +FR,LILLE,"",50.63,3.07,2.20.243.42 +US,PERRYVILLE,MO,37.7127,-89.8903,96.17.14.16 +US,ELKGROVE,CA,38.4313,-121.306,23.61.195.163 +US,ROSLYN,NY,40.8044,-73.641,184.26.44.42 +US,BROOMFIELD,CO,39.9510,-105.0448,63.235.21.140 +US,FONTANA,CA,34.0924,-117.4344,184.50.26.201 +US,LITTLETON,CO,39.5942,-105.0086,107.14.43.30 +GB,LEWISHAM,EN,51.45,-0.02,23.67.255.106 +US,SEMINOLE,FL,27.8440,-82.797,165.254.205.13 +PR,CAYEY,"",18.1193,-66.1642,72.164.253.83 +US,MAINEVILLE,OH,39.3164,-84.2265,165.254.207.111 +US,SINTON,TX,28.0577,-97.5365,96.17.163.161 +US,SEAFORD,DE,38.6412,-75.6063,23.192.161.21 +RU,ORENBURG,"",51.78,55.05,80.239.217.238 +US,PINEBLUFF,AR,34.1930,-91.9403,184.28.23.4 +US,BOYDTON,VA,36.6580,-78.3793,184.27.45.157 +US,WICHITA,KS,37.6923,-97.3374,23.215.15.9 +US,CEDARFALLS,IA,42.5035,-92.4936,23.63.227.225 +US,LITTLEFERRY,NJ,40.8469,-74.0394,24.143.199.156 +US,CALERA,AL,33.1091,-86.7183,23.79.240.48 +DE,SCHWALBACH,HE,50.15,8.53,2.22.61.99 +AW,ORANJESTAD,"",12.52,-70.03,23.74.2.12 +US,HAMPTON,SC,32.9081,-81.0847,184.27.45.150 +US,PITTSBURGH,PA,40.4747,-79.9521,184.26.44.40 +US,WARREN,NJ,40.6309,-74.5141,213.248.117.201 +MA,CASABLANCA,"",33.59,-7.62,92.123.73.26 +US,ALEXANDRIA,VA,38.8194,-77.0596,23.192.161.21 +NC,NOUMEA,"",-22.27,166.45,104.72.70.96 +US,STRUTHERS,OH,41.0502,-80.5914,107.14.38.217 +US,NAPERVILLE,IL,41.7638,-88.1463,107.14.38.224 +US,PASOROBLES,CA,35.6618,-120.7074,23.216.10.54 +US,BELTON,TX,31.0788,-97.4732,184.26.93.116 +DE,WUPPERTAL,NW,51.27,7.18,80.157.170.158 +US,DESOTO,TX,32.5973,-96.864,184.28.23.4 +US,FORTWAINWRIGHT,AK,64.8285,-147.6246,165.254.1.165 +MY,BAHARU,"",6.85,116.83,23.5.165.167 +AU,TOOWOOMBA,QLD,-27.55,151.97,23.62.157.31 +AU,MACKAY,QLD,-21.15,149.20,23.209.183.50 +US,RANCHOPALOSVERDES,CA,33.7553,-118.3641,184.50.26.203 +NZ,GLENFIELD,"",-36.77,174.73,219.88.186.172 +IN,INDORE,MP,22.72,75.83,23.211.135.110 +US,FEDERALWAY,WA,47.3073,-122.3138,23.212.59.90 +CN,XIAN,SN,34.26,108.94,72.246.191.16 +US,MACOMB,MI,42.6839,-82.9078,23.67.60.220 +US,WAPPINGERSFALLS,NY,41.5960,-73.8849,184.51.125.79 +JP,KANAZAWA,17,36.57,136.65,117.104.139.162 +US,MCDONOUGH,GA,33.4474,-84.1473,184.28.127.58 +US,WINDSORMILL,MD,39.3333,-76.7813,23.67.242.156 +US,REEDLEY,CA,36.6362,-119.4115,184.84.180.92 +US,NEWROADS,LA,30.7095,-91.4494,205.185.195.170 +US,LOWELL,MA,42.6562,-71.3029,184.25.109.196 +US,MCLEAN,VA,38.9398,-77.1677,184.27.45.157 +US,SPRINGVILLE,UT,40.1286,-111.4916,23.61.195.165 +US,CAPITOLHEIGHTS,MD,38.9876,-76.8808,23.192.161.21 +RU,PERM,"",58.00,56.25,80.239.217.238 +US,XENIA,OH,39.6596,-83.8999,65.113.249.8 +US,BOULDER,CO,40.0440,-105.194,184.84.180.98 +US,NORCO,CA,33.9289,-117.5482,184.87.195.99 +US,BUCKHANNON,WV,38.9980,-80.2065,184.27.45.150 +FR,ORLEANS,"",47.92,1.90,81.52.201.77 +US,DEQUEEN,AR,34.0794,-94.3022,63.216.54.231 +BN,BANDARSERIBEGAWAN,"",4.88,114.93,23.75.23.140 +DE,COTTBUS,BB,51.77,14.33,80.157.150.169 +NL,UTRECHT,"",52.08,5.13,95.101.2.112 +US,MAMARONECK,NY,40.9533,-73.7381,184.51.125.68 +MX,LOSMOCHIS,SIN,25.77,-108.97,173.223.52.70 +AU,CHATSWOOD,NSW,-33.80,151.18,23.62.8.25 +US,DUNCANVILLE,TX,32.6601,-96.9139,96.16.7.101 +US,FARMINGTON,ME,44.6583,-70.1012,107.14.38.218 +US,RAPIDCITY,SD,44.0755,-103.1782,107.14.38.227 +RU,SAMARA,"",53.20,50.15,80.239.237.80 +US,GIGHARBOR,WA,47.3779,-122.7277,23.212.59.63 +US,NACOGDOCHES,TX,31.6232,-94.6616,23.5.164.146 +US,LACROSSE,WI,43.8000,-91.145,184.85.215.170 +TR,MERSIN,"",36.80,34.63,95.100.169.112 +GB,NOTTINGHAM,EN,52.97,-1.17,88.221.87.94 +JP,NAGANO,20,36.65,138.18,23.3.104.16 +ID,BALI,"",-6.12,106.98,72.246.191.16 +US,WILDOMAR,CA,33.5994,-117.2537,184.50.26.194 +MY,SELANGOR,"",3.35,101.25,203.106.85.13 +US,RHINELANDER,WI,45.6521,-89.3386,184.85.215.170 +BW,GABORONE,"",-24.67,25.92,41.193.163.53 +MU,PORTLOUIS,"",-20.17,57.50,203.106.85.13 +US,DALYCITY,CA,37.6927,-122.4471,23.212.52.88 +JP,KYOTO,26,35.00,135.75,117.104.139.162 +US,MOODY,AL,33.6013,-86.5003,63.216.54.229 +US,CABOT,AR,34.9494,-92.0505,23.5.164.143 +DK,VALBY,"",55.65,12.52,23.65.29.93 +DE,TRAUNSTEIN,BY,47.88,12.65,195.145.147.108 +US,MOUNTLAUREL,NJ,39.9480,-74.9047,23.212.53.64 +US,BROOKLINE,MA,42.3337,-71.1298,184.29.107.20 +CZ,CESKA,"",49.28,16.57,23.74.24.69 +CA,NORTHYORK,ON,43.79,-79.43,72.246.43.232 +MX,MATAMOROS,TAM,25.88,-97.50,165.254.16.86 +TH,DINDAENG,"",12.80,102.08,203.144.145.96 +US,SPANISHFORT,AL,30.6968,-87.8613,96.17.153.157 +GB,SWINDON,EN,51.52,-1.78,96.17.163.165 +US,CHAPELHILL,NC,35.8944,-79.0318,209.18.41.23 +US,EASTPEORIA,IL,40.7043,-89.529,23.67.60.222 +US,SANJACINTO,CA,33.7837,-116.9578,23.216.10.54 +US,WOOSTER,OH,40.8061,-81.9813,107.14.38.227 +BR,JOINVILLE,SC,-26.30,-48.83,72.246.216.144 +US,SIOUXCITY,IA,42.4941,-96.3985,65.113.249.11 +CN,NANCHANG,JX,28.68,115.88,23.76.205.90 +KZ,KARAGANDA,"",49.80,73.10,2.22.52.101 +DE,RECKLINGHAUSEN,NW,51.62,7.20,23.14.94.224 +PF,PAPEETE,"",-17.53,-149.57,64.145.95.126 +FR,CAEN,"",49.18,-0.35,2.20.243.42 +GB,SIDCUP,EN,51.42,0.12,23.61.251.145 +US,PULLMAN,WA,46.7352,-117.1817,212.143.162.169 +US,FORNEY,TX,32.7342,-96.451,23.212.53.64 +US,MERIDIAN,ID,43.6053,-116.4124,192.80.13.117 +US,NIXA,MO,37.0415,-93.3061,23.5.164.143 +US,LAUREL,MD,39.0931,-76.8847,184.28.17.55 +MX,TEPIC,NAY,21.50,-104.90,173.223.52.70 +DE,SINSHEIM,BW,49.26,8.88,80.157.150.197 +LR,MONROVIA,"",6.31,-10.80,217.212.227.31 +US,BEREA,KY,37.5750,-84.2637,23.74.8.8 +US,CANALFULTON,OH,40.8849,-81.5861,205.185.195.183 +NG,LAGOS,"",6.45,3.40,2.20.44.118 +US,SOUTHPASADENA,CA,34.1101,-118.1575,184.50.26.201 +US,LITTLEELM,TX,33.1913,-96.9829,23.5.164.143 +US,LOVELAND,CO,40.3726,-105.133,184.84.180.92 +ZA,SILVERTON,"",-25.73,28.33,165.165.46.40 +US,SHAWNEE,OK,35.3679,-96.9107,174.76.226.117 +IT,TURIN,"",45.05,7.67,2.18.240.114 +US,BRADENTON,FL,27.4044,-82.4667,204.93.33.140 +RO,CLUJNAPOCA,"",46.77,23.60,80.15.235.163 +FR,TOULON,"",43.12,5.93,81.52.201.85 +US,WESTMINSTER,CA,33.7517,-117.9944,184.50.26.201 +US,MALDEN,MA,42.4305,-71.0574,184.25.109.196 +US,MISSOULA,MT,46.8557,-114.0158,107.14.32.228 +US,YAKIMA,WA,46.6267,-120.4248,184.27.179.187 +US,AVENEL,NJ,40.5832,-74.2709,23.67.60.220 +US,NORTHHOLLYWOOD,CA,34.1679,-118.3721,184.50.26.201 +DE,LEER,NI,53.23,7.43,80.157.150.197 +US,REVERE,MA,42.4188,-71.0044,184.25.109.200 +HK,CENTRALDISTRICT,"",22.28,114.15,23.76.205.90 +US,TROUTDALE,OR,45.5277,-122.3738,23.212.59.78 +RU,IVANOVO,"",55.81,36.11,2.21.240.40 +US,MISSION,TX,26.3187,-98.3913,23.215.15.22 +US,FORTBRAGG,CA,39.4588,-123.7157,23.61.195.163 +US,CIRCLEVILLE,OH,39.5752,-82.907,107.14.38.218 +US,BELLEROSE,NY,40.7366,-73.7227,23.67.242.139 +US,POMONA,CA,34.0419,-117.7548,184.50.26.194 +US,MATHER,CA,37.8825,-119.8558,96.17.12.48 +US,EVANS,GA,33.5549,-82.1635,184.27.45.157 +US,HARTFORD,CT,41.7826,-72.6613,184.25.109.200 +NZ,RICCARTON,"",-43.53,172.59,219.88.186.165 +SE,BLACKEBERG,AB,59.35,17.87,213.155.156.207 +UG,KAMPALA,"",0.32,32.58,41.193.163.53 +US,PALMDESERT,CA,33.7547,-116.336,107.14.44.212 +US,MONTEREY,CA,36.5816,-121.8436,96.17.12.48 +US,BECKLEY,WV,37.8169,-81.243,184.28.17.76 +US,SOUTHSANFRANCISCO,CA,37.6562,-122.4257,23.61.195.165 +US,GRANTSPASS,OR,42.6114,-123.7001,206.104.149.146 +US,HUNTSVILLE,AL,34.7252,-86.5616,23.79.240.36 +US,REDBUD,IL,38.1575,-89.9813,23.74.8.8 +CA,HALIFAX,NS,44.65,-63.60,184.29.107.38 +US,EMORY,TX,32.8293,-95.7283,23.212.53.64 +MX,PUEBLA,PUE,19.05,-98.20,23.212.53.75 +US,DEFOREST,WI,43.2338,-89.3318,184.85.215.165 +US,PASCO,WA,46.4588,-118.8176,184.27.179.159 +US,SUGARLAND,TX,29.6334,-95.63,23.212.53.64 +AR,DEMAYO,"",-25.92,-54.58,65.121.209.127 +US,FLORISSANT,MO,38.8119,-90.347,23.215.15.32 +US,FOXBORO,MA,42.0631,-71.2456,184.25.109.196 +CZ,HLUBOKANADVLTAVOU,"",49.05,14.43,23.62.237.138 +US,WILSONVILLE,OR,45.3090,-122.7696,184.27.179.181 +US,MAYNARD,MA,42.4225,-71.4615,184.25.109.196 +US,COLUMBIA,TN,35.6275,-86.9932,23.61.195.163 +US,SUNCITYCENTER,FL,27.7206,-82.4333,23.33.186.134 +US,LEMOORE,CA,36.2897,-119.848,23.212.52.79 +US,ENOLA,PA,40.2947,-76.9833,165.254.96.242 +US,SANTAANA,CA,33.7484,-117.8593,184.50.26.204 +DE,KARLSRUHE,BW,49.00,8.39,23.14.94.228 +AR,DORREGO,"",-38.70,-61.28,200.123.201.215 +DE,GERA,TH,50.87,12.08,194.25.95.219 +US,LEWISTON,ME,44.0905,-70.1653,107.14.38.217 +US,BROWNSVILLE,TX,26.0002,-97.5729,184.26.93.116 +US,LAKEWOOD,CA,33.8539,-118.1333,23.216.10.48 +CA,MARKHAM,ON,43.87,-79.27,72.246.43.215 +US,GREENWOOD,IN,39.6166,-86.1775,23.67.60.220 +RU,VOSTOCHNAYA,"",62.12,34.03,213.155.156.208 +US,WINTERGARDEN,FL,28.5650,-81.5866,23.33.186.134 +US,MELROSEPARK,IL,41.9027,-87.8623,184.27.45.150 +US,CLUTE,TX,29.0650,-95.3887,23.212.53.64 +US,ABSECON,NJ,39.4748,-74.4723,23.61.195.165 +US,ALABASTER,AL,33.2261,-86.7662,72.246.247.30 +US,ELIZABETH,NJ,40.6709,-74.179,184.51.125.79 +MK,SKOPJE,"",42.00,21.43,23.76.205.111 +US,TUSTIN,CA,33.7360,-117.8185,107.14.44.185 +US,ORANGEBURG,SC,33.4964,-80.8317,209.18.41.23 +US,BRYAN,TX,30.6361,-96.3666,204.2.223.90 +US,CHINO,CA,34.0123,-117.6883,184.50.26.201 +US,PIMA,AZ,32.9846,-109.9963,23.212.52.79 +RS,TOPOLA,"",43.88,21.19,184.27.179.159 +US,DAYTON,OH,39.7587,-84.1919,107.14.38.217 +RU,BRYANSK,"",53.24,34.35,2.21.240.40 +US,REGOPARK,NY,40.7254,-73.8614,24.143.199.188 +SG,AYERRAJAH,"",1.30,103.78,203.26.28.181 +AE,FUJAIRAH,"",25.12,56.34,2.20.249.12 +US,WINTERHAVEN,FL,27.9768,-81.764,23.33.186.101 +US,CERES,CA,37.5547,-120.9558,23.216.10.54 +US,GLENVIEW,IL,42.0783,-87.8242,23.67.60.220 +US,BEAUMONT,CA,33.9205,-116.9736,23.216.10.78 +US,SANJUANCAPISTRANO,CA,33.5241,-117.605,23.5.164.143 +US,SHAWNEEMISSION,KS,39.0276,-94.6559,23.77.234.11 +US,BISMARCK,ND,46.8193,-100.7748,107.14.38.218 +PH,DAVAO,"",7.07,125.60,202.78.83.170 +MX,SANPEDROCHOLULA,PUE,19.68,-97.97,201.148.68.240 +FR,CAPELLE,"",49.05,0.48,77.67.27.250 +IR,HAMADAN,"",34.80,48.52,23.62.238.220 +US,NEWHAVEN,CT,41.3083,-72.9287,184.28.17.76 +US,BROCKTON,MA,42.0777,-71.0422,184.25.109.208 +US,TULLAHOMA,TN,35.3402,-86.229,184.51.35.226 +MX,CIUDADOBREGON,SON,27.48,-109.93,187.141.186.95 +UA,KRASNOPEREKOPSK,CRIMEA,45.95,33.79,2.21.240.40 +RU,NAUKA,"",51.97,49.77,80.239.149.123 +UA,DONETSK,"",48.00,37.80,213.155.156.206 +US,NORASPRINGS,IA,43.1638,-92.9674,23.212.53.75 +US,CHALFONT,PA,40.2892,-75.2124,72.247.10.237 +DE,DRESDEN,SN,51.05,13.75,80.157.150.201 +US,TULSA,OK,36.1537,-95.9926,23.212.53.75 +US,ROHNERTPARK,CA,38.3267,-122.7061,23.212.52.79 +US,MOUNTPLEASANT,SC,32.8517,-79.8228,184.27.45.157 +US,WILLIAMSPORT,PA,41.1994,-77.0775,23.192.161.21 +US,FOOTHILLRANCH,CA,33.6255,-117.6932,184.50.26.204 +FR,REIMS,"",49.25,4.03,81.52.201.77 +US,GALION,OH,40.7120,-82.796,23.74.8.24 +BR,FORTALEZA,CE,-3.72,-38.50,190.98.140.184 +US,FERRIS,TX,32.5206,-96.6077,184.25.157.169 +US,CHELSEA,AL,33.3864,-86.611,23.220.100.223 +US,OSSINING,NY,41.1949,-73.8307,184.26.44.38 +BR,MARINGA,PR,-23.42,-51.92,72.246.216.139 +US,ANNANDALE,VA,38.8275,-77.2418,96.6.47.106 +US,PORTER,TX,30.1192,-95.2824,23.212.53.64 +US,PATCHOGUE,NY,40.7718,-72.9949,184.26.44.42 +DE,BIELEFELD,NW,52.03,8.53,80.157.150.197 +US,COLORADOSPRINGS,CO,38.8336,-104.8206,63.151.29.15 +DE,MUNSTER,NW,51.97,7.63,80.157.170.221 +JP,NAHA,47,26.21,127.68,72.246.184.92 +US,TUALATIN,OR,45.3689,-122.7641,184.84.180.92 +US,CLARKSDALE,MS,34.1809,-90.6118,23.212.53.75 +ES,BILBAO,"",43.25,-2.97,77.67.41.223 +US,HALTOMCITY,TX,32.8036,-97.2675,204.93.47.220 +DE,TRIER,RP,49.75,6.63,194.25.95.212 +GB,LEEDS,EN,53.80,-1.58,23.67.255.158 +US,GAMBIER,OH,40.3386,-82.3417,184.27.45.157 +US,CAMBRIDGE,MA,42.3802,-71.1347,184.25.109.200 +US,RIVERTON,UT,40.4909,-112.0097,23.61.195.165 +US,WAYNE,NJ,40.9484,-74.2449,184.26.44.38 +US,CARROLLTON,GA,33.5541,-85.0099,23.79.240.36 +US,PEARLAND,TX,29.5651,-95.2786,23.212.53.64 +US,BELL,CA,33.9704,-118.1852,184.50.26.179 +US,SOUTHLAKE,TX,32.9492,-97.1451,23.215.15.9 +US,DESTREHAN,LA,29.9844,-90.363,174.76.226.110 +US,DESPLAINES,IL,42.0490,-87.8913,107.14.38.218 +DE,DESSAU,ST,51.83,12.25,80.157.170.158 +ZA,PRETORIA,"",-25.71,28.23,165.165.46.40 +US,COLLEGESTATION,TX,30.5416,-96.2298,107.14.43.29 +US,SANDUSKY,MI,43.4191,-82.8598,23.212.53.64 +AU,WAVERLEY,NSW,-33.90,151.27,23.62.8.25 +FR,CLERMONTFERRAND,"",45.78,3.08,2.20.243.45 +US,SOUTHGATE,CA,33.9490,-118.202,184.50.26.203 +ME,PODGORICA,"",42.44,19.26,23.14.94.228 +US,CHATSWORTH,CA,34.2895,-118.607,184.87.195.99 +US,LAKESIDE,CA,32.9105,-116.888,23.216.10.54 +US,LAKEELSINORE,CA,33.5976,-117.3895,184.50.26.179 +US,ROCKFORD,IL,42.3405,-89.1484,23.67.60.222 +EE,TALLINN,"",59.43,24.73,213.155.156.207 +US,ORONO,ME,45.0868,-68.6498,23.74.8.8 +MN,ULAANBAATAR,"",47.92,106.92,23.76.205.90 +US,KETCHIKAN,AK,55.5909,-131.3492,184.27.179.181 +US,LOGAN,UT,41.6898,-111.6435,173.197.192.214 +AT,LINZ,"",48.30,14.30,2.16.217.211 +US,ROUNDROCK,TX,30.5230,-97.6428,107.14.43.30 +US,YUKON,OK,35.5068,-97.7625,23.215.15.9 +RU,POTOK,"",59.46,35.15,23.14.94.224 +VN,DUNG,"",19.83,105.25,23.75.23.135 +JP,KOSE,37,34.47,134.15,23.15.1.55 +BY,GOMEL,"",55.32,28.78,92.122.189.85 +IR,TABRIZ,"",38.08,46.29,23.74.24.69 +RU,TAGIL,"",56.00,51.50,2.21.240.40 +CN,HOHHOT,NM,40.81,111.65,72.246.191.16 +CO,BARRANQUILLA,"",10.98,-74.80,200.14.44.103 +US,MYRTLEBEACH,SC,33.7665,-78.7956,184.27.45.150 +US,SEDALIA,MO,38.6763,-93.2612,65.113.249.8 +US,BOONVILLE,MO,38.8814,-92.7602,96.16.7.101 +CA,OSHAWA,ON,43.90,-78.87,72.246.43.215 +US,PITTSBURG,CA,38.0121,-121.92,23.212.52.79 +US,PORTHURON,MI,42.9793,-82.4643,65.113.249.8 +DE,KALTENBACH,RP,49.20,7.75,80.157.150.197 +US,ELLENDALE,ND,46.0577,-98.4986,107.14.38.224 +US,CARLISLE,PA,40.1805,-77.2345,65.113.249.11 +PR,HUMACAO,"",18.1494,-65.8294,72.246.65.37 +US,MERCED,CA,37.2829,-120.4535,23.212.52.79 +US,TEMPLEHILLS,MD,38.8182,-76.9414,23.192.161.21 +US,LAJOLLA,CA,32.8548,-117.2497,23.216.10.54 +US,BROOKVILLE,OH,39.8424,-84.4242,107.14.38.217 +US,SEVIERVILLE,TN,35.7905,-83.4826,23.79.240.36 +US,SNOHOMISH,WA,47.9468,-122.0122,23.74.8.24 +US,WHITEVILLE,NC,34.2997,-78.6775,184.27.45.157 +US,ELDORADO,AR,33.1732,-92.6868,23.5.164.146 +US,UNIVERSITYPARK,PA,40.8092,-77.8868,96.6.47.120 +US,SUFFOLK,VA,36.8725,-76.5524,96.6.47.120 +CA,LETHBRIDGE,AB,49.70,-112.83,24.244.17.205 +BR,BELEM,PA,-1.45,-48.48,177.159.174.13 +CN,KUNMING,YN,25.04,102.72,72.246.191.19 +BY,MINSK,"",53.90,27.57,2.20.142.173 +AU,LOXTON,SA,-34.45,140.57,60.254.143.219 +US,CORAM,NY,40.8776,-73.0024,184.26.44.42 +DE,LUBECK,SH,53.87,10.70,194.25.95.214 +US,GREATLAKES,IL,42.3045,-87.8638,23.67.60.223 +US,CARTHAGE,NY,43.9769,-75.558,107.14.38.227 +NZ,DUNEDIN,"",-45.87,170.50,219.88.186.164 +US,DICKSON,TN,36.0826,-87.4349,23.79.240.36 +US,RUIDOSO,NM,33.3909,-105.6341,173.223.52.67 +BR,BELOHORIZONTE,MG,-19.92,-43.93,200.174.107.50 +DE,ROSTOCK,MV,54.08,12.13,194.25.95.214 +US,WILKESBORO,NC,36.1256,-81.1459,204.93.62.75 +DE,WEIDEN,RP,49.82,7.30,2.16.217.206 +US,IRONMOUNTAIN,MI,45.9025,-88.0366,165.254.207.117 +US,LYNWOOD,CA,33.9236,-118.2003,184.87.195.99 +RU,YAROSLAVL,"",57.62,39.87,2.21.240.40 +US,PACOIMA,CA,34.2561,-118.4203,184.50.26.179 +US,BARTLETT,IL,41.9753,-88.1848,23.67.60.217 +CA,SIMCOE,ON,42.83,-80.30,72.246.43.232 +US,SUMMERVILLE,SC,33.0633,-80.1896,209.18.41.27 +US,JEFFERSONCITY,MO,38.5003,-92.1516,209.170.117.178 +US,LAFAYETTE,LA,30.2373,-91.9924,23.215.15.22 +US,CHESAPEAKE,VA,36.7522,-76.2168,23.212.53.64 +CH,DIETIKON,"",47.42,8.40,193.45.15.198 +RU,VLADIVOSTOK,"",43.13,131.90,96.7.251.95 +US,EXTON,PA,40.0430,-75.64,23.67.242.139 +US,CAROLSTREAM,IL,41.9125,-88.1349,107.14.38.217 +MY,KUALAKANGSAR,"",4.77,100.93,58.26.185.142 +US,TUCKER,GA,33.8539,-84.2185,72.246.247.30 +CN,GUOJI,JS,34.06,117.41,23.15.10.106 +US,MIAMISBURG,OH,39.6178,-84.2528,107.14.38.217 +US,DEKALB,IL,41.8888,-88.7558,23.67.60.223 +FR,NIMES,"",43.83,4.35,2.16.117.190 +BR,SALVADOR,BA,-12.98,-38.52,200.174.107.42 +US,NORTON,MA,41.9632,-71.1829,23.62.238.215 +US,BOTHELL,WA,47.7527,-122.2153,184.84.180.101 +US,TROY,OH,40.0416,-84.1531,23.74.8.8 +US,STAFFORD,VA,38.4716,-77.4391,184.26.44.40 +US,ORRVILLE,OH,40.8369,-81.7632,2.22.52.101 +US,LEBANON,MO,37.6765,-92.6098,63.216.54.216 +US,WACO,TX,31.5520,-97.1385,23.212.53.64 +FR,CHOISYLEROI,"",48.77,2.42,2.16.117.190 +US,HARTSVILLE,SC,34.3720,-80.0853,209.18.41.27 +US,FAIRVIEW,OR,45.5383,-122.4348,23.212.59.90 +US,GLENDORA,CA,34.1187,-117.8538,184.50.26.204 +US,CRANSTON,RI,41.7750,-71.4355,23.67.244.226 +US,MUNDELEIN,IL,42.2666,-88.0352,107.14.38.217 +US,NILES,IL,42.0285,-87.8124,23.67.60.222 +US,SEBASTIAN,FL,27.7861,-80.4788,23.79.240.48 +RU,YAKUTSK,"",62.00,129.67,2.21.240.40 +RU,ULYANOVSK,"",52.12,34.41,217.212.227.25 +AU,BALAKLAVA,SA,-34.15,138.42,210.11.142.65 +DE,BAUTZEN,SN,51.18,14.43,80.157.150.201 +US,WORCESTER,MA,42.2627,-71.8028,63.141.200.248 +CH,VERNIER,"",46.22,6.08,193.247.167.214 +TR,DENIZLI,"",40.90,29.53,193.45.15.199 +US,HOUMA,LA,29.5867,-90.8252,23.212.53.75 +US,EASTWENATCHEE,WA,47.4725,-120.2224,184.27.179.179 +US,NORTHPOLE,AK,64.7816,-147.3481,23.212.59.64 +US,GALLATIN,TN,36.4052,-86.4555,23.79.240.36 +CA,AYLMER,ON,42.78,-80.98,72.246.43.237 +US,ODESSA,TX,31.8458,-102.3673,23.212.53.75 +US,CHALMETTE,LA,29.9614,-89.9537,23.215.15.18 +US,SOUTHYARMOUTH,MA,41.6739,-70.1961,184.25.109.196 +US,SIGNALHILL,CA,33.7834,-118.1506,184.50.26.179 +US,HARRISONBURG,VA,38.5056,-78.9398,184.28.17.76 +US,FRANKLIN,VA,36.6905,-76.9426,184.28.17.76 +US,MISSOURICITY,TX,29.5470,-95.5308,23.212.53.75 +US,CLERMONT,FL,28.4862,-81.7428,72.164.253.83 +US,CHERAW,SC,34.6398,-79.9151,209.18.41.23 +US,SOUTHHILL,VA,36.7430,-78.1806,184.29.107.38 +US,LAGUNAHILLS,CA,33.5987,-117.7127,184.50.26.203 +SG,BEDOK,"",1.33,103.94,23.75.23.135 +US,LANGDON,ND,48.8344,-98.3538,63.216.54.231 +US,BALLWIN,MO,38.6038,-90.5556,204.93.47.216 +US,TULIA,TX,34.5509,-101.7483,23.74.8.24 +JP,MATSUSAKA,24,34.57,136.53,23.15.1.29 +RU,UFA,"",54.73,55.93,217.212.227.25 +US,SANRAFAEL,CA,37.9769,-122.5052,23.212.52.79 +SK,BRATISLAVA,"",48.15,17.12,23.14.94.220 +US,LOCKPORT,NY,43.1860,-78.742,184.29.107.20 +KZ,SHYMKENT,"",42.30,69.60,80.239.222.190 +MD,CHISINAU,"",47.01,28.86,92.122.189.114 +US,PLATTSBURGH,NY,44.7370,-73.4626,63.141.200.248 +GB,HARINGEY,EN,51.58,-0.08,23.67.255.158 +US,OSKALOOSA,IA,41.3158,-92.6258,65.113.249.8 +CA,GUELPH,ON,43.55,-80.25,67.231.211.237 +US,HILLSBORO,OR,45.4461,-122.9838,63.217.232.22 +US,PLAINFIELD,NJ,40.6310,-74.4312,184.26.44.42 +IN,DEHRADUN,UL,30.32,78.03,96.17.182.130 +ES,ZARAGOZA,"",41.63,-0.88,80.149.168.109 +US,SANBERNARDINO,CA,34.1053,-117.2917,23.216.10.78 +US,LITCHFIELD,CT,41.7562,-73.2062,184.51.125.68 +DE,MEPPEN,NI,52.68,7.32,80.157.170.231 +FR,BOISDARCY,"",48.80,2.02,2.16.117.190 +SI,LJUBLJANA,"",46.06,14.51,23.62.237.138 +US,CONVERSE,TX,29.5102,-98.277,184.26.93.116 +US,RARITAN,NJ,40.5726,-74.6423,184.26.44.38 +US,DEVINE,TX,29.1707,-98.9599,96.17.163.161 +reserved,reserved,reserved,reserved,reserved,63.80.12.225 +DE,DEGGINGEN,BW,48.60,9.72,23.14.94.224 +US,PIEDMONT,SC,34.7207,-82.4772,23.79.240.48 +US,MANHATTANBEACH,CA,33.8907,-118.3967,23.216.10.54 +IR,TEHRAN,"",35.67,51.42,184.29.107.20 +US,ITHACA,NY,42.4320,-76.4974,69.31.77.208 +US,NORWALK,CA,33.9069,-118.082,23.216.10.54 +US,WILLOUGHBY,OH,41.6111,-81.3789,107.14.38.224 +US,RUSSELLVILLE,AR,35.2872,-93.0945,23.5.164.143 +US,WATSONVILLE,CA,36.9274,-121.7472,63.233.61.151 +US,LORENA,TX,31.3976,-97.22,107.14.43.29 +GB,OLDHAM,EN,53.55,-2.12,88.221.87.94 +US,SPRINGDALE,AR,36.1895,-94.2305,23.215.15.9 +US,WASCO,CA,35.6321,-119.4058,184.87.195.109 +US,NORTHEAST,MD,39.5890,-75.9588,23.192.161.16 +CN,CHONGQING,CQ,29.56,106.55,23.76.205.90 +BD,MEDIA,"",23.13,89.18,23.57.76.20 +NZ,NAPIER,"",-39.48,176.92,219.88.186.164 +US,HENDERSON,NV,36.0394,-114.9813,165.254.144.32 +US,PEORIA,AZ,33.5921,-112.4065,184.50.26.179 +US,THOMASVILLE,NC,35.8640,-80.1016,209.18.41.23 +US,HOPEMILLS,NC,34.9210,-78.9114,209.18.41.27 +KG,BISHKEK,"",42.90,74.60,80.239.217.238 +US,UPPERDARBY,PA,39.9602,-75.2702,184.29.107.20 +JP,TOKUSHIMA,36,34.07,134.57,72.246.184.84 +US,CLARKSVILLE,TN,36.5878,-87.3074,165.254.138.175 +US,RIDGECREST,CA,35.7401,-117.4536,184.50.26.179 +RO,ROSIORIIDEVEDE,"",44.12,24.98,81.196.26.237 +US,RENO,NV,39.5263,-119.8124,23.216.10.78 +US,KENOSHA,WI,42.6168,-87.8302,65.113.249.11 +BY,BREST,"",52.10,23.70,217.212.227.31 +US,GREENFIELD,IN,39.7974,-85.7653,65.113.249.11 +IE,CASHEL,"",52.52,-7.89,88.221.222.34 +US,STARKVILLE,MS,33.4256,-88.8438,208.185.55.117 +LT,KAUNAS,"",54.90,23.90,2.21.240.61 +DE,WESEL,NW,51.67,6.62,80.157.170.154 +US,WESTERNSPRINGS,IL,41.8114,-87.9019,23.67.60.223 +DE,WURZBURG,BY,49.79,9.94,195.145.147.109 +US,SANRAMON,CA,37.7661,-121.9734,23.61.195.165 +DE,MAGDEBURG,ST,52.17,11.67,80.157.150.201 +US,CROWNPOINT,IN,41.4039,-87.3294,23.67.60.223 +US,PALMHARBOR,FL,28.0778,-82.7637,192.204.11.246 +SE,SODERTALJE,AB,59.20,17.62,2.21.240.61 +US,LAMONI,IA,40.6492,-93.957,23.67.60.223 +US,KEYLARGO,FL,25.2553,-80.3918,23.79.240.36 +PL,ZAMOSC,"",52.13,21.12,2.22.52.109 +US,MOORPARK,CA,34.2858,-118.8813,63.235.21.147 +US,GARDNERVILLE,NV,38.7983,-119.574,184.85.249.14 +US,EVERETT,WA,47.9874,-122.2011,23.212.59.63 +US,SYLMAR,CA,34.3277,-118.3895,184.50.26.201 +US,LAWRENCEVILLE,GA,33.9563,-83.9881,23.79.240.36 +CA,PRINCERUPERT,BC,54.32,-130.33,184.27.179.181 +US,GLADSTONE,OR,45.3872,-122.5921,23.212.59.63 +US,HARWOODHEIGHTS,IL,41.9530,-87.7822,23.67.60.223 +US,SAINTCHARLES,IL,41.9372,-88.2876,107.14.38.224 +US,COVINA,CA,34.0976,-117.9068,23.216.10.54 +VN,PHUONG,"",17.17,106.92,23.2.16.104 +US,VERNONHILLS,IL,42.2230,-87.9651,23.67.60.223 +RU,TAMBOV,"",52.73,41.43,80.239.237.231 +MM,YANGON,"",16.78,96.17,203.106.85.13 +CH,PULLY,"",46.52,6.65,193.247.167.211 +US,HICKORY,NC,35.7628,-81.3219,23.79.240.37 +US,HOLLYSPRINGS,NC,35.6211,-78.8587,63.151.29.15 +GB,NEWBURY,EN,51.40,-1.32,23.212.108.8 +US,SOUTHSALEM,NY,41.2554,-73.5385,184.26.44.42 +US,FORTWAYNE,IN,41.1306,-85.1289,23.67.60.223 +US,TAYLOR,MI,42.2256,-83.2685,23.67.60.222 +IN,GUNTUR,AP,16.30,80.45,23.57.69.161 +US,CUMBERLAND,MD,39.6528,-78.7626,184.28.17.55 +US,LANHAM,MD,38.9666,-76.8622,184.27.45.157 +RU,SAKHALIN,"",52.43,32.90,2.22.52.102 +US,NORFOLK,VA,36.8511,-76.2784,184.28.127.58 +US,YOUNGSTOWN,OH,41.0994,-80.6494,96.17.9.8 +CA,VERNON,BC,50.27,-119.27,24.244.17.205 +US,CASPER,WY,43.1744,-106.3605,107.14.32.228 +US,ELLICOTTCITY,MD,39.2673,-76.7986,23.67.242.139 +TW,TAICHUNG,"",24.15,120.68,61.220.62.175 +US,HACKENSACK,NJ,40.8892,-74.0466,23.67.242.139 +US,BONNEYLAKE,WA,47.1879,-122.183,23.212.59.85 +US,YORK,PA,39.9626,-76.7282,23.192.161.16 +DE,HAGEN,NW,51.03,7.43,195.95.193.147 +FR,POITIERS,"",46.58,0.33,2.20.243.45 +BR,COTIA,SP,-23.62,-46.93,72.246.216.139 +US,MILFORD,MA,42.1566,-71.5186,184.25.109.200 +DE,NEUBRANDENBURG,MV,53.57,13.27,195.95.193.132 +US,WILLIAMSBURG,KY,36.7356,-84.1501,23.220.148.122 +US,BENTONVILLE,AR,36.3232,-94.2666,23.77.234.11 +FR,TOULOUSE,"",43.60,1.43,2.20.243.45 +CA,YELLOWKNIFE,NT,62.45,-114.35,184.150.187.229 +US,COUDERSPORT,PA,41.7605,-77.9728,209.18.41.23 +DE,BRAUNSCHWEIG,NI,52.27,10.53,194.25.95.214 +AU,MIRANDA,NSW,-34.03,151.10,23.62.8.25 +US,SYLVANIA,OH,41.6992,-83.7379,23.74.8.24 +US,WESTCHESTER,PA,39.9842,-75.6084,184.27.45.157 +US,TULARE,CA,36.1798,-119.3666,23.212.52.79 +US,ELMHURST,NY,40.7372,-73.8787,184.29.107.38 +GR,IOANNINA,"",39.67,20.83,23.14.94.214 +JP,ASAHI,14,35.53,139.70,72.246.191.16 +US,LANSING,MI,42.7327,-84.5558,65.113.249.8 +US,TRABUCOCANYON,CA,33.6636,-117.5894,184.50.26.194 +US,CLEARWATER,FL,27.9797,-82.7794,72.164.253.83 +US,MORGANTON,NC,35.7567,-81.7518,23.79.240.48 +US,SIERRAMADRE,CA,34.1687,-118.0505,184.50.26.204 +US,SPRINGHILL,FL,28.4679,-82.5981,23.33.186.134 +US,TYLER,TX,32.3248,-95.3025,165.254.207.117 +US,IOWACITY,IA,41.6899,-91.4517,65.113.249.8 +US,MUSKOGEE,OK,35.6818,-95.3578,23.5.164.143 +US,LAKECHARLES,LA,30.2894,-93.0808,96.17.153.162 +US,LAKESTEVENS,WA,48.0434,-122.062,23.212.59.90 +JO,AL,"",31.82,35.83,80.239.154.193 +US,CARIBOU,ME,46.8928,-68.1493,107.14.38.218 +BG,PAZARDJIK,"",42.20,24.33,23.62.237.137 +JP,MATSUYAMA,38,33.84,132.76,184.51.199.132 +US,UNIVERSALCITY,TX,29.5519,-98.3081,107.14.43.30 +US,SIERRAVISTA,AZ,31.5436,-110.254,184.50.26.194 +US,VIRGINIABEACH,VA,36.8598,-75.9812,23.220.148.122 +AU,DANDENONG,VIC,-37.98,145.20,23.62.8.25 +CA,MISSISSAUGA,ON,43.15,-79.50,67.231.211.247 +CA,BRAMPTON,ON,43.68,-79.77,72.246.43.233 +UZ,ANDIJAN,"",40.78,72.34,2.22.52.105 +US,WHARTFORD,CT,41.7542,-72.7573,184.25.109.213 +JP,TAKAMATSU,37,34.33,134.05,117.104.139.136 +SO,MOGADISCIO,"",2.07,45.37,80.239.237.230 +US,SARASOTA,FL,27.3364,-82.5308,192.204.11.235 +AT,PURGSTALL,"",48.75,15.72,195.145.147.108 +RU,TOLYATTI,"",53.52,49.41,80.239.217.238 +US,MARQUETTE,MI,46.5095,-87.3836,184.85.215.170 +IN,KOCHI,KL,9.97,76.23,117.239.240.76 +US,EASTMAN,GA,32.2112,-83.1979,72.246.247.30 +US,ALBEMARLE,NC,35.3503,-80.2174,63.216.54.229 +US,CONCORD,NC,35.3735,-80.5212,209.18.41.27 +US,MOUNTPROSPECT,IL,42.0663,-87.9341,23.67.60.223 +DE,JENA,TH,50.93,11.58,23.14.94.220 +US,PERRY,GA,32.4431,-83.7439,23.215.15.22 +ES,ZAMUDIO,"",43.28,-2.87,92.123.73.221 +FR,DIJON,"",47.32,5.02,2.20.243.42 +US,MORENOVALLEY,CA,33.8879,-117.225,184.50.26.179 +US,YUCAIPA,CA,34.0360,-117.0172,184.50.26.179 +AU,BELROSE,NSW,-33.73,151.22,23.62.8.21 +US,DRIPPINGSPRINGS,TX,30.2468,-98.1159,65.116.149.102 +US,ONTARIO,CA,34.0635,-117.6503,184.50.26.179 +US,RIGBY,ID,43.6749,-111.8908,67.131.104.6 +US,ROCKVILLE,MD,39.0839,-77.1534,96.6.47.120 +US,CUYAHOGAFALLS,OH,41.1403,-81.4761,96.17.9.8 +US,WESTLAND,MI,42.3351,-83.3852,65.113.249.11 +CA,MILLBROOK,ON,44.15,-78.45,72.246.43.237 +GB,HAYES,EN,51.37,0.02,88.221.87.94 +CZ,HAVLICKUVBROD,"",49.62,15.58,23.62.237.135 +SI,MARIBOR,"",46.55,15.65,213.248.108.233 +JP,IBARAKI,27,34.82,135.57,202.229.2.213 +DE,OSNABRUCK,NI,52.27,8.05,80.157.170.231 +RU,MURMANSK,"",68.48,33.35,2.21.240.61 +US,WYLIE,TX,33.0138,-96.5409,23.215.15.32 +US,DADECITY,FL,28.3653,-82.1963,23.33.186.101 +US,DOYLESTOWN,PA,40.3369,-75.1195,65.113.249.11 +GB,BRENTFORD,EN,51.50,-0.32,23.67.255.158 +US,ROCKWALL,TX,32.8846,-96.42,96.16.7.120 +US,WAVERLY,OH,39.1500,-83.0509,107.14.38.227 +US,ABERDEEN,WA,47.1445,-123.7718,184.84.180.101 +US,TOLEDO,OH,41.6525,-83.5486,23.74.8.24 +US,SANPABLO,CA,37.9790,-122.3365,23.212.52.79 +US,LAGUNANIGUEL,CA,33.5425,-117.7825,184.50.26.194 +US,DEPEW,NY,42.9001,-78.7029,184.26.44.38 +US,LOSALTOS,CA,37.3688,-122.1527,23.212.52.88 +US,WATERFORD,CT,41.3583,-72.1558,165.254.48.150 +US,ASHEVILLE,NC,35.5948,-82.5572,23.79.240.37 +US,DENTON,TX,33.2208,-97.1437,204.93.47.216 +US,EPHRATA,PA,40.1811,-76.176,63.216.54.236 +US,DICKINSON,ND,46.9271,-102.7543,205.185.195.183 +US,PANAMACITY,FL,30.1608,-85.6475,23.212.53.75 +ID,MEDAN,"",3.58,98.67,23.0.162.46 +US,SUNLAND,CA,34.2589,-118.3307,107.14.44.212 +US,SANTAMARIA,CA,34.9332,-120.2665,23.212.52.79 +US,LEMONGROVE,CA,32.7331,-117.0343,184.50.26.179 +US,BRIDGETON,NJ,39.4433,-75.2554,184.26.44.38 +US,FLORENCE,OR,44.1259,-124.0315,165.254.96.248 +FR,BORDEAUX,"",44.83,-0.57,81.52.201.77 +VN,CANTHO,"",10.03,105.78,96.17.180.177 +MO,MACAU,"",22.20,113.55,202.175.5.87 +US,QUEENCREEK,AZ,33.3064,-111.8406,63.226.34.173 +AO,LUANDA,"",-8.82,13.23,23.62.100.154 +DE,SACK,BY,49.50,11.02,23.14.94.224 +EC,CUENCA,"",-2.88,-78.98,165.254.205.7 +US,LAKEWORTH,FL,26.6214,-80.0578,23.79.240.37 +US,MATTHEWS,NC,35.0912,-80.6904,63.216.54.236 +JP,SAPPORO,01,43.05,141.35,72.246.184.89 +US,CHANTILLY,VA,38.8959,-77.4456,184.85.249.6 +US,WESTMONT,IL,41.7959,-87.9751,107.14.38.218 +US,MORGANCITY,LA,29.8739,-91.2977,23.215.15.9 +US,OAKBROOK,IL,41.7836,-87.9391,23.67.60.222 +US,GREENSBORO,NC,36.0706,-79.7656,72.246.247.30 +US,CORTLAND,NY,42.5863,-76.1831,72.247.10.237 +AT,WIENERNEUDORF,"",48.07,16.32,195.145.147.108 +CZ,PRAHA,"",50.08,14.47,23.62.237.133 +NA,WINDHOEK,"",-22.57,17.08,41.193.163.53 +SZ,MBABANE,"",-26.32,31.13,41.193.163.45 +US,MANNING,SC,33.6434,-80.1966,184.51.35.215 +US,LOVETTSVILLE,VA,39.2666,-77.6386,2.20.142.166 +US,ISLIP,NY,40.7426,-73.2171,184.26.44.38 +US,MESQUITE,TX,32.7700,-96.614,107.14.43.30 +US,FERGUSFALLS,MN,46.2829,-96.0991,165.254.207.117 +AR,RIVADAVIA,"",-34.85,-58.37,184.50.26.179 +US,LASCRUCES,NM,32.6621,-106.6414,23.212.52.79 +US,GLASSBORO,NJ,39.6996,-75.1187,23.67.242.156 +KR,KISA,"",36.72,126.80,92.122.215.89 +US,PETALUMA,CA,38.2181,-122.773,23.212.52.88 +RU,KOLOMNA,"",55.08,38.78,213.155.156.212 +US,YUCCAVALLEY,CA,34.2832,-116.5958,184.50.26.203 +CL,VINADELMAR,"",-33.01,-71.52,190.98.143.69 +CA,THUNDERBAY,ON,48.40,-89.23,72.246.43.215 +US,CORPUSCHRISTI,TX,27.7980,-97.4011,23.212.53.75 +IN,VASHI,MH,18.75,73.03,23.57.69.157 +VN,DONGDA,"",22.63,106.40,23.5.165.167 +US,SEVERNAPARK,MD,39.0808,-76.5571,23.67.242.156 +US,ASHLAND,OR,42.1843,-122.5624,23.212.59.90 +ID,MALANG,"",-7.98,112.62,23.0.162.21 +GB,ASHFORD,EN,51.42,-0.47,23.67.255.158 +RU,SVERDLOVSK,"",56.85,60.60,2.21.240.40 +US,WESTERVILLE,OH,40.1219,-82.9191,96.17.9.14 +US,SULPHURSPRINGS,TX,33.1779,-95.567,23.5.164.146 +US,RATHDRUM,ID,47.8426,-116.9074,107.14.43.30 +US,EATON,CO,40.5202,-104.6808,23.215.15.9 +US,RIVERFALLS,WI,44.8561,-92.6272,23.67.60.222 +US,ANTELOPE,CA,38.7156,-121.3637,23.212.52.93 +SE,SKARHOLMEN,AB,59.28,17.88,217.212.227.25 +US,HEARNE,TX,30.8324,-96.5749,23.212.53.75 +US,WAUSAU,WI,45.0598,-89.4871,23.74.8.24 +US,ELGIN,IL,42.0350,-88.2392,23.67.60.222 +UZ,TASHKENT,"",40.13,68.37,2.21.240.61 +NP,KATHMANDU,"",27.72,85.32,23.212.108.8 +US,LAWRENCE,KS,39.0131,-95.2254,23.63.227.214 +US,ALPHARETTA,GA,34.1327,-84.2992,72.246.247.30 +US,ODENTON,MD,39.0496,-76.7176,23.192.161.21 +EC,QUITO,"",-0.22,-78.50,165.254.205.13 +TW,TAINAN,"",23.31,120.31,61.220.62.175 +CN,NINGBO,ZJ,29.88,121.54,23.15.10.106 +US,MANAHAWKIN,NJ,39.7102,-74.2577,184.26.44.42 +RU,ROSTOVNADONU,"",47.24,39.71,23.14.94.228 +US,"","",38.7657,-77.4852,184.25.157.169 +RU,CHELYABINSK,"",55.17,61.40,213.155.156.206 +US,WALLACE,NC,34.7667,-77.8738,63.151.29.15 +FI,ESPOO,"",60.22,24.67,193.184.164.219 +US,BATONROUGE,LA,30.4499,-91.1876,96.17.153.162 +FI,KAJAANI,"",64.23,27.68,193.184.164.219 +US,GROVERBEACH,CA,35.1287,-120.6191,23.216.10.54 +US,HUNTINGDON,PA,40.6074,-77.8631,23.192.161.16 +US,SIMIVALLEY,CA,34.2707,-118.7905,184.50.26.204 +US,BUTLER,PA,40.9096,-79.9361,65.121.209.127 +US,GARDENCITY,MI,42.3244,-83.3417,23.67.60.222 +IT,CAGLIARI,"",39.22,9.12,213.144.173.198 +MX,AGUASCALIENTES,AGU,21.88,-102.30,23.215.15.22 +US,OWASSO,OK,36.2942,-95.797,72.164.253.68 +TR,INKILAP,"",36.75,37.53,23.61.195.163 +US,DULUTH,MN,47.1196,-91.8629,23.63.227.227 +US,VALDOSTA,GA,30.7579,-83.3062,72.246.247.5 +US,PFLUGERVILLE,TX,30.4432,-97.5977,204.2.223.90 +US,EDMOND,OK,35.6833,-97.5261,23.63.227.227 +FI,VANTAA,"",60.30,24.85,82.96.58.102 +RU,KALUGA,"",54.54,36.27,80.239.217.238 +US,MENA,AR,34.5920,-94.1901,96.16.7.101 +ID,JOGJAKARTA,"",-7.80,110.37,23.0.162.40 +US,PEVELY,MO,38.2842,-90.4297,204.93.47.220 +US,WESTROXBURY,MA,42.2799,-71.1623,23.192.161.21 +PH,LEGASPI,"",15.82,120.60,202.78.83.170 +CN,YUETAN,AH,29.65,118.14,184.50.87.178 +US,HUMMELSTOWN,PA,40.2988,-76.709,23.192.161.30 +ID,TENGAH,"",-3.18,113.32,23.0.162.40 +UY,MONTEVIDEO,"",-34.88,-56.18,200.40.28.31 +BR,PELOTAS,RS,-31.77,-52.33,187.59.4.154 +GN,CONAKRY,"",9.51,-13.71,213.200.109.183 +KR,KIMCHON,"",36.12,128.12,125.56.214.149 +US,CORNING,NY,42.0806,-77.0397,209.18.41.23 +ML,BAMAKO,"",12.65,-8.00,81.52.201.82 +BY,GRODNO,"",53.68,23.83,80.239.222.190 +US,CORAOPOLIS,PA,40.5042,-80.1934,184.27.45.150 +CA,TROISRIVIERES,QC,46.35,-72.55,72.246.43.233 +US,SPARKS,NV,39.5386,-119.7498,23.216.10.78 +US,NORWICH,CT,41.5523,-72.0921,184.25.109.213 +US,HATTIESBURG,MS,31.1996,-89.2694,72.246.247.5 +US,CLIFTONHEIGHTS,PA,39.9228,-75.2984,184.28.17.76 +US,CENTRALIA,WA,46.7386,-122.9449,23.212.59.85 +US,JONESBORO,GA,33.5203,-84.3178,23.79.240.37 +JO,AMMAN,"",31.95,35.93,77.67.27.250 +US,MASSENA,NY,44.9476,-74.9244,107.14.38.217 +US,BRISTOL,VA,36.6927,-82.2134,209.48.37.188 +US,SAINTGEORGE,UT,37.1317,-113.7959,165.254.144.25 +US,CLAREMONT,CA,34.1276,-117.7153,173.223.52.70 +US,NEWBERG,OR,45.3226,-122.99,184.27.179.181 +US,MADERA,CA,36.9046,-120.1728,23.212.52.88 +AU,MARULAN,NSW,-34.70,150.02,202.7.177.87 +US,LAHABRA,CA,33.9421,-117.9517,23.216.10.54 +TR,KAYSERI,"",38.72,35.50,2.21.240.61 +US,CLINTONTOWNSHIP,MI,42.5574,-82.8963,23.67.60.222 +US,GLOBE,AZ,33.5677,-110.7249,63.226.34.174 +US,APACHEJUNCTION,AZ,33.4152,-111.5488,63.226.34.162 +DE,HAG,BW,47.73,7.92,2.16.217.211 +US,WAXHAW,NC,34.9191,-80.7283,209.18.41.23 +US,BEVERLYHILLS,CA,34.0738,-118.3994,63.141.193.62 +RU,KALININGRAD,"",55.92,37.88,2.21.240.40 +US,DELAWARE,OH,40.3029,-83.0602,107.14.38.227 +DE,OFFENBURG,BW,48.48,7.93,80.157.150.197 +US,CLEARFIELD,UT,41.1230,-112.0639,63.217.232.17 +US,PIKEVILLE,KY,37.5348,-82.513,184.27.45.157 +US,THIBODAUX,LA,29.8127,-90.7428,96.17.153.157 +US,LATHROP,CA,37.8212,-121.2919,96.17.12.48 +US,HAZEN,ND,47.3960,-101.6023,107.14.38.227 +AT,SALZBURG,"",47.80,13.03,195.145.147.108 +US,NEVADA,MO,37.8504,-94.3445,23.77.234.35 +US,DUMFRIES,VA,38.5915,-77.3508,184.28.17.76 +US,MACON,GA,32.8993,-83.468,184.51.35.226 +CN,SHENZHEN,GD,22.53,114.13,184.50.87.176 +US,KALAMA,WA,46.0150,-122.7836,192.80.13.117 +US,ROCKLIN,CA,38.8019,-121.2492,96.17.12.48 +US,WINTER,WI,45.8255,-90.8897,23.74.8.8 +US,SCHOOLCRAFT,MI,42.1212,-85.6839,23.74.8.24 +TN,TUNIS,"",36.80,10.18,46.33.70.213 +US,BERGENFIELD,NJ,40.9234,-73.9981,184.26.44.38 +FR,VITRYSURSEINE,"",48.78,2.40,2.16.117.200 +US,PEYTON,CO,39.0051,-104.5039,63.151.29.12 +PL,LUBLIN,"",51.25,22.57,2.22.52.101 +US,LAKEWALES,FL,27.8661,-81.4384,184.51.35.226 +US,POWAY,CA,32.9789,-117.0196,23.216.10.54 +FR,MONTOISON,"",44.78,4.92,2.16.117.190 +US,MONTCLAIR,CA,34.0753,-117.6972,184.50.26.179 +KR,MOKPO,"",34.79,126.39,61.111.58.229 +US,OWINGSMILLS,MD,39.4250,-76.7779,23.192.161.16 +FJ,SUVA,"",-18.13,178.42,104.72.70.95 +US,PORTERVILLE,CA,36.0318,-118.9656,23.216.10.78 +US,LINDEN,NJ,40.6259,-74.2395,23.67.242.156 +PL,KRASNIK,"",50.92,22.23,2.22.52.109 +US,DUNNELLON,FL,29.0187,-82.4395,23.33.186.134 +LB,BEIRUT,"",33.87,35.51,95.101.34.105 +DE,HEIDELBERG,BW,49.42,8.70,23.14.94.224 +KZ,TALDYKURGAN,"",45.00,77.92,2.20.142.173 +US,LAKEFOREST,CA,33.6490,-117.6848,184.50.26.179 +RU,IRKUTSK,"",52.27,104.33,217.212.227.31 +US,NEWBURYPARK,CA,34.1843,-118.9097,184.50.26.204 +US,MARINADELREY,CA,33.9786,-118.4476,184.50.26.204 +US,WETUMPKA,AL,32.5691,-86.1584,72.246.247.5 +US,NORTHTAZEWELL,VA,37.1608,-81.5125,107.14.43.30 +US,ALLENTOWN,PA,40.6019,-75.4727,184.29.107.38 +US,BAYSAINTLOUIS,MS,30.3134,-89.5231,96.17.153.157 +US,PEACHTREECITY,GA,33.3924,-84.5695,72.246.247.5 +US,ONEONTA,NY,42.4787,-75.0181,107.14.38.218 +US,HACIENDAHEIGHTS,CA,33.9955,-117.9764,107.14.44.212 +US,HARVEY,LA,29.8673,-90.069,96.17.153.162 +US,ELKTON,VA,38.3599,-78.6227,23.192.161.16 +US,ALBERTVILLE,AL,34.3010,-86.1927,72.246.247.5 +IE,CORK,"",51.90,-8.50,95.101.2.112 +US,DUBOIS,PA,41.1434,-78.731,184.26.44.38 +US,SOUTHHADLEY,MA,42.2564,-72.5775,165.254.202.96 +US,HATBORO,PA,40.1770,-75.1061,184.26.44.42 +NZ,NAENAE,"",-41.20,174.94,219.88.186.172 +ID,SEMARANG,"",-6.97,110.42,23.14.94.228 +US,SYRACUSE,NY,43.0499,-76.1506,107.14.38.227 +US,RIDGELAND,MS,32.4200,-90.1289,23.79.240.48 +US,NORTHAMPTON,MA,42.3230,-72.6707,184.25.109.213 +US,STOCKBRIDGE,GA,33.5641,-84.1952,23.79.240.36 +CZ,PLZEN,"",49.75,13.37,2.22.52.105 +PL,REDA,"",54.62,18.35,2.22.52.109 +US,BRIGHTON,CO,39.9758,-104.8092,23.212.53.75 +US,NEWPORT,AR,35.5678,-91.2073,23.5.164.143 +ES,OVIEDO,"",43.37,-5.83,80.149.168.111 +US,CANOGAPARK,CA,34.1977,-118.6018,184.87.195.109 +US,BENTON,KY,36.8777,-88.361,107.14.38.217 +US,MONTEREYPARK,CA,34.0511,-118.144,23.216.10.78 +US,LAMESA,CA,32.7605,-116.9997,184.50.26.194 +FI,YLIVIESKA,"",64.08,24.55,193.184.164.237 +HK,SHATIN,"",22.38,114.18,219.76.10.81 +BB,BRIDGETOWN,"",13.10,-59.62,23.74.2.7 +PL,ELBLAG,"",54.17,19.38,2.22.52.109 +US,COMPTON,CA,33.8794,-118.2368,184.50.26.201 +US,STATESBORO,GA,32.4474,-81.7452,184.27.45.157 +US,OAKDALE,CA,37.7848,-120.7726,96.17.12.48 +BR,GUARULHOS,SP,-23.47,-46.53,200.174.107.50 +FR,RENNES,"",48.08,-1.68,2.20.243.42 +IN,SION,MH,19.03,72.85,96.17.180.166 +US,DESTIN,FL,30.3934,-86.4958,184.51.35.226 +US,JENKS,OK,36.0001,-95.9806,23.215.15.32 +US,FORESTGROVE,OR,45.6684,-123.3405,184.27.179.181 +US,GREENCASTLE,IN,39.6767,-86.9214,23.63.227.227 +US,TAYLORVILLE,IL,39.5521,-89.3216,23.63.227.227 +MX,SANPEDROGARZAGARCIA,NLE,25.41,-99.91,184.26.93.116 +US,CONROE,TX,30.3059,-95.4359,204.2.223.91 +US,HYATTSVILLE,MD,38.9534,-76.9444,23.192.161.16 +JP,FUJITA,07,37.87,140.55,72.246.191.19 +US,ESPANOLA,NM,35.9775,-106.1582,63.216.54.229 +US,BULLHEADCITY,AZ,35.1469,-114.5576,23.5.164.146 +PL,KOLOBRZEG,"",54.18,15.58,2.22.52.101 +FR,ASNIERES,"",48.92,2.28,88.221.15.111 +US,STILLWATER,OK,36.0774,-97.0817,107.14.43.30 +US,GREELEY,CO,40.4475,-104.6861,184.84.180.68 +NZ,CHRISTCHURCH,"",-43.53,172.63,203.97.86.239 +US,LEESVILLE,LA,31.2063,-93.1344,204.2.223.90 +US,SCITUATE,MA,42.2010,-70.7631,184.26.44.42 +UA,ALUSHTA,CRIMEA,44.67,34.42,80.239.222.167 +US,VACAVILLE,CA,38.3470,-121.9283,165.254.45.13 +US,NEWHALL,CA,34.3744,-118.4762,184.50.26.194 +ID,DEPOK,"",-6.40,106.83,202.43.190.246 +US,HILO,HI,19.6686,-155.3062,165.254.96.248 +DE,NEUSS,NW,51.20,6.68,2.16.217.211 +US,LAJUNTA,CO,37.8368,-103.544,107.14.32.228 +DE,OLPE,NW,51.03,7.85,80.157.170.154 +ID,BOGOR,"",-6.15,106.98,23.0.162.54 +AU,WOLLONGONG,NSW,-34.43,150.88,23.62.157.32 +US,WOODSTOCK,GA,34.1201,-84.4649,23.212.53.64 +US,SILVERDALE,WA,47.7228,-122.7145,23.212.59.63 +US,SMITHFIELD,UT,41.8466,-111.898,184.84.180.101 +US,ABILENE,TX,32.4816,-99.6841,23.5.164.146 +PR,GUAYNABO,"",18.3658,-66.0928,72.246.65.26 +GB,EXETER,EN,50.70,-3.53,88.221.87.94 +US,LAGRANGE,GA,33.0069,-85.1034,23.79.240.36 +US,ARCADIA,CA,34.1380,-118.0283,165.254.144.25 +US,RIVERBANK,CA,37.7323,-120.941,96.17.12.44 +DE,TRAUBING,BY,47.95,11.27,195.145.147.107 +US,MONTEVISTA,CO,37.5196,-106.1764,107.14.32.228 +US,ALISOVIEJO,CA,33.5767,-117.7127,63.151.119.16 +US,SAINTCLOUD,FL,28.2446,-81.2943,23.33.186.101 +US,WESTMIFFLIN,PA,40.3582,-79.9065,23.192.161.16 +DE,KEMPTEN,BY,47.72,10.32,194.25.95.214 +US,BATAVIA,NY,42.9969,-78.2158,107.14.38.224 +MX,CULIACAN,SIN,24.00,-107.03,173.223.52.70 +US,POCATELLO,ID,42.8976,-112.3706,65.116.149.89 +EE,TARTU,"",58.37,26.74,82.96.58.102 +JP,KANDA,07,37.20,140.38,202.229.2.213 +US,BAYSIDE,NY,40.7918,-73.7759,184.26.44.38 +US,BUFORD,GA,34.1046,-84.0037,23.79.240.37 +RU,KIROV,"",54.83,36.47,80.239.222.190 +US,ROWLANDHEIGHTS,CA,33.9850,-117.9013,184.50.26.204 +US,CULLOWHEE,NC,35.2608,-83.1173,184.27.45.157 +US,AUBURN,AL,32.6014,-85.5082,204.2.243.135 +DE,KRONBERG,HE,50.18,8.50,92.122.188.163 +AU,IPSWICH,QLD,-27.62,152.77,23.62.157.32 +SE,GAVLE,X,60.67,17.17,213.155.156.207 +US,METAIRIE,LA,29.9840,-90.1664,96.17.153.157 +US,HERCULES,CA,38.0074,-122.2624,23.212.52.79 +US,PRESCOTT,AZ,34.7884,-112.8659,63.226.34.176 +US,SAYRE,PA,41.9771,-76.4144,107.14.38.217 +FR,NOISYLEGRAND,"",48.85,2.57,2.16.117.190 +US,TAPPAHANNOCK,VA,37.9112,-76.9715,208.185.55.86 +ID,YOGYAKARTA,"",-7.80,110.37,23.0.162.40 +FR,LOGNES,"",48.83,2.62,2.16.117.200 +PL,SZCZECIN,"",51.92,19.72,80.239.222.169 +US,ARANSASPASS,TX,27.9093,-97.1497,23.215.15.9 +ID,PALEMBANG,"",-2.92,104.75,96.17.180.177 +US,LAREDO,TX,27.5137,-99.5021,23.5.164.146 +US,QUAKERTOWN,PA,40.4606,-75.3304,184.26.44.42 +GB,ALFRETON,EN,53.10,-1.38,195.245.125.114 +CA,HINTON,AB,53.40,-117.58,24.244.17.205 +US,SEWARD,NE,40.8874,-97.126,107.14.43.30 +PL,WROCLAW,"",51.10,17.03,2.22.61.102 +US,SANTACLARITA,CA,34.5130,-118.4027,184.50.26.204 +US,AVON,CO,39.5815,-106.4966,184.84.180.68 +KZ,BELOUSOVKA,"",50.13,82.52,2.21.240.40 +IN,CHANDIGARH,CH,30.74,76.79,117.239.91.75 +US,CROSBY,TX,29.9299,-95.0527,23.212.53.75 +CN,QIAOTOU,ZJ,30.15,121.36,23.15.10.112 +US,FLORA,IL,38.6705,-88.5031,23.74.8.8 +DE,KIEL,SH,54.33,10.13,194.25.95.225 +RU,OMSK,"",55.00,73.40,2.21.240.61 +US,PALMCITY,FL,27.1320,-80.3491,23.79.240.48 +US,NEEDHAM,MA,42.2750,-71.2465,184.25.109.200 +US,CHARLESTON,WV,38.3510,-81.6265,184.27.45.157 +US,CENTERCONWAY,NH,43.9597,-71.0453,165.254.35.197 +US,VALLEY,AL,32.7858,-85.1946,23.79.240.36 +US,FRENCHCAMP,CA,37.8805,-121.2989,23.212.52.88 +US,STUDIOCITY,CA,34.1386,-118.3879,107.14.44.185 +DE,KONSTANZ,BW,47.67,9.18,194.25.95.225 +US,URBANDALE,IA,41.6320,-93.7353,65.113.249.8 +US,AUSTELL,GA,33.8340,-84.6343,72.246.247.5 +US,NEWCASTLE,DE,39.6483,-75.6041,23.192.161.30 +RU,TYUMEN,"",58.52,48.27,80.239.237.84 +US,BELMAR,NJ,40.1783,-74.0222,184.51.125.79 +FR,AMBERIEUENBUGEY,"",45.92,4.73,2.16.117.200 +US,ORANGEVALE,CA,38.6892,-121.2198,23.212.52.82 +US,BROKENARROW,OK,35.9842,-95.8102,63.216.54.229 +FR,ALFORTVILLE,"",48.80,2.42,2.16.117.190 +US,BLOOMSBURG,PA,41.0301,-76.4558,23.67.242.139 +US,FERNDALE,WA,48.8653,-122.6362,23.212.59.64 +US,MORGANTOWN,WV,39.5846,-79.9182,23.192.161.16 +VN,BINHTHANH,"",10.77,106.75,96.17.180.177 +IN,LUDHIANA,PB,30.90,75.85,23.211.135.66 +AR,ROSARIO,"",-32.95,-60.67,200.123.201.215 +RU,GRAN,"",50.72,39.78,80.239.217.231 +US,WATERLOO,IL,38.3034,-90.1358,23.63.227.227 +CA,COURTENAY,BC,49.68,-125.00,184.27.179.187 +US,LEWISBURG,WV,37.8469,-80.447,184.28.17.55 +US,ELMWOODPARK,NJ,40.9049,-74.1196,23.67.242.156 +US,JOPLIN,MO,37.1074,-94.5218,23.215.15.9 +ID,BARAT,"",-7.57,111.45,202.43.190.246 +US,PHOENIXVILLE,PA,40.1221,-75.5397,23.192.161.16 +US,GRETNA,LA,29.9128,-90.0524,23.215.15.22 +US,SHEFFIELDLAKE,OH,41.4650,-82.0929,107.14.32.235 +US,SILVERSPRING,MD,39.0245,-77.0094,96.6.47.120 +CA,REDDEER,AB,52.27,-113.80,184.27.179.187 +US,MORTONGROVE,IL,42.0422,-87.789,23.67.60.223 +ZA,ISANDO,"",-26.15,28.20,41.193.163.45 +US,HAINESCITY,FL,28.0703,-81.5695,192.204.11.244 +JP,OKI,33,34.62,134.13,72.246.184.92 +US,KINGSPORT,TN,36.4877,-82.6162,184.29.107.20 +US,CASTLEROCK,CO,39.3765,-104.8554,184.84.180.92 +US,CENTEREACH,NY,40.8699,-73.0833,184.26.44.42 +TR,DIYARBAKIR,"",37.92,40.23,193.45.15.199 +AR,LARIOJA,"",-29.43,-66.85,190.98.167.220 +US,OROVILLE,CA,39.5324,-121.6485,63.151.119.25 +FR,LIGNE,"",50.67,2.33,23.67.255.158 +DZ,ALGIERS,"",36.76,3.05,213.200.109.183 +US,TUPELO,MS,34.2235,-88.7398,23.220.100.223 +US,RACINE,WI,42.7263,-87.7829,165.254.96.242 +CN,TAIZHOU,ZJ,28.85,121.12,72.246.191.19 +US,OREGONCITY,OR,45.3306,-122.529,23.212.59.85 +PL,LODZ,"",51.75,19.47,80.239.222.169 +US,BROWNSBURG,IN,39.8655,-86.3812,65.113.249.8 +MX,GUAYMAS,SON,27.93,-110.90,173.223.52.70 +US,DOUGLASVILLE,GA,33.7516,-84.7478,23.79.240.37 +US,SUISUNCITY,CA,38.2546,-122.0486,23.212.52.88 +US,HALETHORPE,MD,39.2187,-76.722,23.192.161.16 +US,MIDDLETON,ID,43.7467,-116.5805,192.80.13.108 +US,NEWBEDFORD,MA,41.6384,-70.9419,184.25.109.196 +CA,SAINTLAURENT,QC,45.52,-73.67,72.246.43.237 +US,PORTCHARLOTTE,FL,26.9751,-82.152,23.79.240.36 +US,MIDDLERIVER,MD,39.3459,-76.3996,23.192.161.21 +US,VERONA,NJ,40.8330,-74.2435,23.74.8.24 +BR,CAMPINAS,SP,-22.90,-47.08,200.174.107.42 +US,TOPEKA,KS,39.0486,-95.6778,23.77.234.35 +GB,BRENT,EN,51.55,-0.27,92.122.126.82 +US,YORKTOWN,VA,37.2346,-76.5585,23.220.148.108 +US,SANLUIS,AZ,32.4906,-114.7753,184.50.26.201 +ID,MAKASSAR,"",2.45,99.78,118.98.42.129 +US,QUINLAN,TX,32.9155,-96.1709,107.14.43.30 +US,LINDALE,GA,34.1582,-85.1905,23.79.240.37 +US,CEDARPARK,TX,30.4956,-97.8267,23.215.15.9 +KR,TAEJON,"",36.32,127.42,183.111.23.63 +PL,GOGOLIN,"",53.40,18.67,2.22.52.109 +PH,MANDALUYONG,"",14.58,121.03,120.28.5.110 +US,WARRINGTON,PA,40.2476,-75.1421,23.67.242.139 +CZ,BLANSKO,"",50.70,14.10,195.27.155.188 +IN,BHUBANESHWAR,OR,20.23,85.83,23.57.76.20 +US,WARWICK,NY,41.2642,-74.3694,184.51.125.79 +US,AMERICANFORK,UT,40.4102,-111.814,184.84.180.101 +US,OXNARD,CA,34.2254,-119.1713,23.216.10.78 +MX,MAZATLAN,SIN,23.22,-106.42,173.223.52.67 +US,HAGERSTOWN,MD,39.6364,-77.7249,168.143.243.33 +US,URBANA,IL,40.1590,-88.187,23.63.227.214 +US,SUMMERFIELD,FL,28.9926,-82.0497,23.79.240.48 +US,HAMMOND,IN,41.6065,-87.4967,23.67.60.222 +US,MOAB,UT,38.6903,-109.2562,184.85.249.14 +JP,IWAMI,28,34.78,134.53,23.3.74.113 +US,GALVESTON,TX,29.3093,-94.7816,23.212.53.75 +US,COALTOWNSHIP,PA,40.7855,-76.5082,184.26.44.38 +US,LUBBOCK,TX,33.5838,-101.8403,23.5.164.143 +US,HAUGHTON,LA,32.5391,-93.5257,96.17.153.162 +PS,GAZA,"",31.50,34.47,95.100.169.105 +US,TALLAHASSEE,FL,30.4294,-84.2579,69.31.132.229 +PL,OSIELSKO,"",53.18,18.07,80.239.222.190 +US,LAGRANDE,OR,45.2284,-118.272,165.254.1.165 +US,WOODBURN,OR,45.1385,-122.8359,184.27.179.159 +US,HOLBROOK,NY,40.7951,-73.0765,184.26.44.38 +LV,CESIS,"",57.30,25.25,213.155.156.206 +US,FORTHUACHUCA,AZ,31.5925,-110.3847,204.94.155.235 +US,MOUNTAINHOMEAFB,ID,43.0653,-116.032,206.104.149.146 +US,HAVERFORD,PA,40.0078,-75.3135,184.26.44.35 +US,MECHANICSBURG,PA,40.2485,-77.0142,23.67.242.156 +US,PARSIPPANY,NJ,40.8553,-74.3996,184.51.125.68 +US,GREENBAY,WI,44.4814,-88.0196,23.63.227.214 +YE,SANA,"",15.35,44.21,79.140.94.183 +US,BESSEMER,AL,33.4077,-86.9494,204.2.243.132 +MX,ZAPOPAN,JAL,20.72,-103.40,23.215.15.9 +US,OGDEN,UT,41.2234,-111.9731,23.61.195.165 +US,GRANITECITY,IL,38.7259,-90.0982,69.31.97.120 +US,MUNCIE,IN,40.1286,-85.3767,204.93.47.220 +US,KNOXVILLE,TN,35.9646,-83.9197,23.79.240.37 +US,APPLEVALLEY,CA,34.5744,-117.1146,63.233.61.151 +US,SHEBOYGAN,WI,43.7072,-87.7387,23.63.227.227 +US,SCHAUMBURG,IL,42.0334,-88.0833,107.14.38.224 +BR,GOIANIA,GO,-16.67,-49.27,200.174.107.42 +US,HERKIMER,NY,43.0566,-75.0112,107.14.38.218 +NL,DELFT,"",52.00,4.37,2.16.153.173 +TW,CHIAI,"",23.48,120.44,61.220.62.175 +US,DEPERE,WI,44.4310,-88.1738,107.14.38.218 +US,SOUDERTON,PA,40.2970,-75.3345,184.26.44.42 +US,MONTVILLE,CT,41.4628,-72.1545,165.254.48.150 +RO,RAMNICUVALCEA,"",45.10,24.37,81.196.26.237 +AT,ETZELSDORF,"",47.95,14.05,195.145.147.108 +US,SIMPSONVILLE,SC,34.6913,-82.2915,23.79.240.37 +CA,FORTMCMURRAY,AB,56.73,-111.38,24.244.17.197 +US,CARSONCITY,NV,39.1386,-119.6595,23.216.10.78 +PH,DILIMAN,"",14.63,121.07,202.78.83.175 +US,CAPECANAVERAL,FL,28.3971,-80.6086,96.6.47.106 +US,SOMERVILLE,MA,42.3814,-71.0971,184.29.107.20 +CN,QUANZHOU,FJ,24.90,118.58,184.50.87.178 +GB,BASILDON,EN,51.57,0.47,23.67.255.158 +KW,KUWAIT,"",29.37,47.98,63.80.12.225 +US,DOWNERSGROVE,IL,41.8086,-88.0231,23.215.15.9 +US,YORKSHIRE,NY,42.5238,-78.4755,184.26.44.42 +FR,BEZONS,"",48.93,2.22,2.16.117.190 +US,WARMINSTER,PA,40.2185,-75.0735,23.192.161.16 +US,HERRIMAN,UT,40.4909,-112.0097,23.61.195.163 +US,MONTEBELLO,CA,34.0167,-118.1107,63.151.119.25 +US,DAYTONABEACH,FL,29.1935,-81.0536,184.51.145.22 +US,LACEY,WA,47.0254,-122.7992,23.212.59.63 +CM,YAOUNDE,"",3.87,11.52,184.84.239.175 +US,BRYNMAWR,PA,40.0226,-75.3301,23.67.242.139 +US,OWENSBORO,KY,37.7353,-87.2433,107.14.38.218 +JP,KUMAGAYA,11,36.13,139.38,202.239.172.94 +US,EGGHARBORTOWNSHIP,NJ,39.3650,-74.6283,184.26.44.38 +RU,BARNAUL,"",55.65,66.27,2.21.240.40 +PL,BYTOM,"",50.35,18.97,2.22.52.105 +CN,HARBIN,HL,45.75,126.65,72.246.191.19 +US,PLYMOUTH,IN,41.3572,-86.3281,23.67.60.223 +US,LEANDER,TX,30.5580,-97.9247,184.28.23.24 +IN,NIWAS,MP,23.05,80.43,124.124.252.153 +BY,VITEBSK,"",55.19,30.19,92.122.189.114 +US,EVANSVILLE,IN,37.9744,-87.5555,23.63.227.227 +JP,KAGOSHIMA,46,31.60,130.55,202.229.2.212 +US,JAMAICA,NY,40.6917,-73.8061,209.18.41.27 +ZA,NORTHCLIFF,"",-26.13,27.95,165.165.46.37 +DE,POTSDAM,BB,52.40,13.07,195.95.193.150 +JP,CHIBA,12,35.60,140.12,104.74.70.98 +US,NORTHFIELD,MN,44.4726,-93.1785,184.85.215.170 +US,BRENHAM,TX,30.2352,-96.4076,204.2.223.91 +US,MONTROSE,CA,34.2114,-118.231,23.216.10.54 +US,SNYDER,TX,33.0123,-100.8338,23.215.15.9 +ID,BARU,"",-6.13,106.78,23.0.162.40 +US,JOHNSONCITY,TN,36.3400,-82.3328,23.79.240.36 +US,FORTWALTONBEACH,FL,30.4494,-86.6242,183.111.23.63 +AE,ABUDHABI,"",24.47,54.37,23.5.164.146 +JP,NIIGATA,15,37.92,139.05,117.104.139.162 +US,JASPER,GA,34.4645,-84.4746,184.28.127.58 +US,TALLMADGE,OH,41.1018,-81.4225,107.14.38.217 +CA,BOWMANVILLE,ON,43.90,-78.68,72.246.43.232 +TR,ULUS,"",39.93,32.87,193.45.15.198 +US,GLENELLYN,IL,41.8564,-88.062,23.67.60.220 +US,ANDERSON,IN,40.1325,-85.7642,65.113.249.11 +US,WEXFORD,PA,40.6275,-80.0614,72.246.52.107 +US,NICEVILLE,FL,30.4944,-86.0572,184.51.35.226 +US,DEARBORN,MI,42.3055,-83.1724,63.141.200.241 +US,EASTLIVERPOOL,OH,40.6788,-80.5838,23.192.161.21 +US,NEWPORTBEACH,CA,33.6187,-117.9283,23.215.15.22 +US,DEBARY,FL,28.8805,-81.3193,23.212.53.75 +BY,MOGILEV,"",53.91,30.34,23.14.94.224 +US,NORCROSS,GA,33.9378,-84.2013,72.246.247.30 +RU,KAZAN,"",55.75,49.13,2.21.240.61 +RO,SIBIU,"",45.80,24.15,81.196.26.231 +CZ,FRENSTATPODRADHOSTEM,"",49.55,18.22,23.62.237.133 +CN,HAIKOU,HI,20.05,110.34,72.246.191.19 +US,SOUTHRICHMONDHILL,NY,40.6884,-73.8234,184.26.44.42 +US,EDMONDS,WA,47.8000,-122.3719,23.212.59.63 +US,WINCHESTER,TN,35.1786,-86.12,23.212.53.64 +US,CENTRALPOINT,OR,42.4072,-122.9556,192.80.13.117 +US,JESUP,GA,31.5041,-81.8277,23.79.240.48 +US,ALIEF,TX,29.7106,-95.5963,23.212.53.64 +JP,UJI,26,34.88,135.80,23.3.74.112 +JP,TAMA,33,34.48,133.93,118.155.230.132 +US,ELMENDORFAFB,AK,61.2646,-149.8047,23.212.59.85 +IN,JAISALMER,RJ,26.92,70.90,184.25.157.169 +US,MUKILTEO,WA,47.9095,-122.3022,23.212.59.85 +US,HOBOKEN,NJ,40.7453,-74.032,23.67.242.139 +DE,EBERSWALDE,BB,52.83,13.83,92.122.207.179 +US,YUMA,AZ,32.7006,-114.6726,184.50.26.179 +US,HYDEN,KY,37.1647,-83.4362,184.51.35.226 +US,ARDMORE,PA,40.0021,-75.2992,23.67.242.139 +US,CEDARHILL,TX,32.5815,-96.9616,107.14.43.30 +RU,TIS,"",57.01,57.60,80.239.217.231 +US,UNION,NJ,40.6941,-74.2694,184.26.44.38 +US,BELLEVILLE,IL,38.4985,-89.9796,204.93.47.216 +IT,BOLZANO,"",46.52,11.37,213.144.173.218 +US,NOBLE,OK,35.1418,-97.2907,64.129.104.135 +US,HUTCHINSON,KS,38.0313,-98.1636,23.215.15.22 +US,PULASKI,VA,37.0726,-80.7961,184.26.44.40 +CY,LEMESOS,"",34.67,33.03,2.20.142.173 +BG,KLIMENT,"",42.60,24.68,80.239.222.167 +DE,BRANDENBURG,BB,52.42,12.55,80.157.150.169 +US,ORMONDBEACH,FL,29.2856,-81.0563,184.51.145.7 +US,WOODSIDE,NY,40.7439,-73.9053,184.29.107.20 +US,OREGON,OH,41.6550,-83.4472,23.74.8.24 +US,FORTMOHAVE,AZ,35.0028,-114.5797,24.143.194.216 +IR,KERMANSHAH,"",34.31,47.06,213.155.156.212 +US,NOBLESVILLE,IN,40.0583,-85.9657,23.67.60.222 +RU,ZHIGULI,"",53.35,49.30,2.21.240.40 +US,CHAMPLIN,MN,45.1692,-93.3912,23.67.60.223 +US,DELANO,CA,35.7580,-119.1095,184.87.195.109 +CY,PAPHOS,"",34.77,32.42,173.223.52.70 +US,SALIDA,CA,37.7163,-121.0942,23.216.10.54 +US,BENSENVILLE,IL,41.9552,-87.9401,107.14.38.224 +US,LONGMONT,CO,40.1771,-105.0797,184.84.180.92 +US,PROVO,UT,40.2247,-111.6938,63.80.12.225 +JP,YAMAGUCHI,35,34.17,131.48,184.51.199.132 +AU,PENNANTHILLS,NSW,-33.73,151.07,23.205.116.7 +US,STATESVILLE,NC,35.7886,-80.8801,96.16.12.216 +US,NORTHAURORA,IL,41.8068,-88.3366,23.67.60.223 +US,BEAR,DE,39.5786,-75.7006,184.26.44.38 +AU,LIVERPOOL,NSW,-33.90,150.93,23.62.8.25 +US,CLAREMORE,OK,36.3346,-95.5666,23.215.15.22 +DE,BAUMGARTEN,BY,50.15,11.47,80.157.150.192 +US,CHATTANOOGA,TN,35.0459,-85.3097,184.51.35.215 +US,GRAPEVINE,TX,32.9275,-97.0735,192.204.11.244 +US,AMES,IA,42.0383,-93.6284,204.93.47.216 +RO,GALATI,"",45.85,24.97,2.22.52.102 +US,ACWORTH,GA,34.0445,-84.7171,23.79.240.37 +US,GOLDSBORO,NC,35.4141,-78.0215,209.18.41.23 +ID,SURABAYA,"",-4.67,105.72,118.98.37.99 +US,GALLUP,NM,35.4315,-108.7243,63.226.34.173 +US,UPLAND,CA,34.1381,-117.6589,23.216.10.78 +US,OAKPARK,CA,34.1839,-118.7702,184.50.26.179 +US,CALABASAS,CA,34.1257,-118.6769,184.50.26.179 +IT,COMO,"",45.78,9.08,213.144.173.218 +US,MUSCLESHOALS,AL,34.7605,-87.6264,72.246.247.30 +US,BAUDETTE,MN,48.5595,-94.661,23.212.53.75 +US,LAWRENCEBURG,IN,39.1597,-84.8764,23.74.8.8 +US,KENMORE,WA,47.7577,-122.2428,23.212.59.85 +US,DELAND,FL,28.9706,-81.4214,184.51.145.22 +US,COMSTOCKPARK,MI,43.0682,-85.6853,65.113.249.8 +HT,PETIONVILLE,"",18.51,-72.29,23.74.2.7 +US,CHICO,CA,39.9285,-121.8223,184.84.180.101 +RO,BRAILA,"",45.27,27.98,81.196.26.231 +US,TINLEYPARK,IL,41.5679,-87.7949,23.67.60.222 +RU,FRYAZINO,"",55.96,38.05,213.155.156.212 +US,FALLRIVER,MA,41.7314,-71.1164,184.25.109.196 +US,SAINTJOSEPH,MO,39.7657,-94.8425,23.5.164.143 +SA,ALKHOBAR,"",26.28,50.21,79.140.94.183 +US,MONMOUTH,OR,44.7727,-123.3556,192.80.13.117 +US,GLENSIDE,PA,40.1012,-75.1722,23.67.242.156 +US,RESTON,VA,38.9597,-77.3374,65.121.209.125 +RU,EKATERINBURG,"",56.85,60.60,2.21.240.61 +US,PENSACOLA,FL,30.4205,-87.2234,184.51.35.226 +US,ADAMSVILLE,AL,33.5928,-86.9876,23.220.100.223 +PL,DEBICA,"",51.65,22.57,80.239.222.169 +US,ALAMOGORDO,NM,32.7929,-106.161,63.226.34.176 +IT,SAVONA,"",44.28,8.50,213.144.173.218 +US,SOUTHELGIN,IL,41.9935,-88.277,107.14.38.218 +US,GOODYEAR,AZ,33.4238,-112.4015,63.226.34.176 +US,KENNESAW,GA,34.0374,-84.5922,72.246.247.5 +DZ,CONSTANTINE,"",36.37,6.61,79.140.94.183 +IN,JAIPUR,RJ,26.92,75.82,96.17.182.136 +US,ANNANDALEONHUDSON,NY,42.0124,-73.8998,184.29.107.20 +US,CARPINTERIA,CA,34.6066,-119.5558,173.223.52.70 +US,GAINESVILLE,GA,34.3157,-83.8152,23.79.240.37 +US,LANSDALE,PA,40.2305,-75.2995,23.77.238.9 +YE,SANAA,"",15.35,44.21,184.84.180.98 +NL,THEHAGUE,"",52.08,4.30,92.122.189.114 +US,KINGFISHER,OK,35.9153,-98.0257,174.76.226.117 +US,DOVER,NH,43.1854,-70.9128,184.25.109.213 +PR,MAYAGUEZ,"",18.1211,-67.0824,64.86.201.118 +US,ZION,IL,42.4565,-87.8597,107.14.38.218 +US,SEYMOUR,CT,41.3811,-73.0868,184.25.109.196 +DE,DEGGENDORF,BY,48.83,12.97,84.53.146.39 +VE,MARACAIBO,"",10.63,-71.64,72.246.65.37 +US,VALLEYVILLAGE,CA,34.1666,-118.3996,184.50.26.179 +AT,INNSBRUCK,"",47.27,11.40,95.100.169.112 +US,MORRIS,IL,41.3973,-88.4715,23.67.60.223 +US,BANNING,CA,33.9464,-116.8543,23.216.10.78 +US,VINELAND,NJ,39.5016,-75.0264,184.26.44.38 +UA,TERNOPOL,"",49.55,25.58,23.14.94.220 +IN,BALAJINAGAR,TN,13.12,80.23,96.17.180.166 +US,BOUNTIFUL,UT,40.8715,-111.8314,23.61.195.160 +FR,RUEILMALMAISON,"",48.88,2.20,2.16.117.200 +US,PITTSFORD,NY,43.0476,-77.5243,23.79.240.36 +KR,KWANGJU,"",35.15,126.92,23.65.188.30 +US,TRAVISAFB,CA,38.2626,-121.9405,63.217.232.22 +US,BONIFAY,FL,30.8908,-85.6931,2.21.240.61 +GB,COSHAM,EN,50.83,-1.07,23.67.255.158 +US,JANESVILLE,WI,42.6846,-89.1369,184.85.215.165 +JP,FUKUOKA,40,33.58,130.40,117.104.139.162 +NZ,TIMARU,"",-44.40,171.25,219.88.186.164 +MM,RANGOON,"",16.78,96.17,96.17.180.166 +US,NORTHLASVEGAS,NV,36.2132,-115.1197,65.116.149.89 +US,PORTRICHEY,FL,28.3040,-82.7021,23.33.186.134 +US,PAINTSVILLE,KY,37.7517,-82.9074,184.28.17.76 +US,LIVEOAK,FL,30.2764,-83.0529,23.79.240.37 +US,POPLARBLUFF,MO,36.7803,-90.4373,23.63.227.227 +BE,LIEGE,"",50.63,5.57,2.18.243.1 +US,FORTLEE,NJ,40.8502,-73.9734,184.26.44.38 +RO,IP,"",47.23,22.65,80.239.222.169 +US,LEOMINSTER,MA,42.5209,-71.7716,184.25.109.201 +US,CHILLICOTHE,OH,39.3125,-83.0274,107.14.38.224 +US,SAINTPAULPARK,MN,44.8338,-92.9932,63.151.29.12 +PL,GDANSK,"",54.35,18.67,2.22.52.102 +US,WYNNE,AR,35.2584,-90.8369,173.197.194.166 +US,CASSELBERRY,FL,28.6630,-81.3122,23.33.186.101 +US,PIKESVILLE,MD,39.3860,-76.7222,96.6.47.120 +TW,TAOYUAN,"",24.27,121.25,203.69.138.118 +AT,HEIDENREICHSTEIN,"",48.87,15.12,195.145.147.108 +CN,HUAIHUA,HN,27.55,109.95,72.246.191.16 +RU,LENIN,"",48.30,40.88,213.248.108.233 +US,WINNETKA,CA,34.2090,-118.5753,184.87.195.99 +US,STIGLER,OK,35.2928,-95.0844,174.76.226.110 +US,GREENCOVESPRINGS,FL,29.9530,-81.7369,184.51.145.7 +AR,MARGARITA,"",-31.70,-61.65,190.98.167.220 +US,CLEMENTON,NJ,39.8055,-74.9997,184.26.44.38 +US,DARBY,PA,39.9168,-75.2677,184.26.44.40 +US,CARLYLE,IL,38.5905,-89.3709,23.63.227.214 +RU,IZHEVSK,"",56.85,53.23,92.122.215.67 +US,RANCHOCORDOVA,CA,38.5857,-121.2825,96.17.12.44 +US,WATERTOWN,MA,42.3708,-71.1833,184.29.107.20 +US,KEARNEY,NE,40.7317,-98.9983,184.85.215.165 +AU,BRAESIDE,VIC,-37.98,145.12,184.84.221.116 +GQ,MALABO,"",3.75,8.78,2.20.44.118 +US,TWENTYNINEPALMS,CA,34.1466,-115.8753,184.50.26.179 +RW,KIGALI,"",-1.96,30.04,41.193.163.45 +US,LAMIRADA,CA,33.9172,-118.0114,184.50.26.179 +US,HOTSPRINGSNATIONALPARK,AR,34.5331,-93.0035,66.171.227.82 +US,STERLINGHEIGHTS,MI,42.5651,-83.0651,23.67.60.222 +DE,LUE,BY,49.58,12.15,2.16.217.211 +US,JOHNSTOWN,PA,40.3358,-78.9111,23.192.161.16 +US,PAOLI,PA,40.0429,-75.48,23.67.242.139 +US,BLAIR,NE,41.5565,-96.2448,23.79.255.149 +US,HUNTERSVILLE,NC,35.4108,-80.8434,209.18.41.27 +TH,NAKHONRATCHASIMA,"",14.97,102.12,61.19.12.164 +AU,BUNBURY,WA,-33.33,115.63,202.7.177.76 +GB,BROMSGROVE,EN,52.33,-2.07,23.67.255.158 +DE,HALLE,ST,51.50,12.00,80.157.150.192 +CU,HAVANA,"",23.13,-82.36,72.246.65.38 +US,FONDDULAC,WI,43.7436,-88.3886,184.85.215.165 +US,ORCHARDPARK,NY,42.7477,-78.7413,107.14.38.227 +CN,JIAXING,ZJ,30.77,120.75,72.246.191.19 +US,EDINBURG,TX,26.3620,-98.1616,184.26.93.116 +US,SHAWANO,WI,44.7924,-88.6722,23.74.8.24 +US,COTTONWOOD,AZ,34.6334,-112.1256,63.226.34.174 +CN,XINING,QH,36.62,101.77,72.246.191.19 +US,VENTURA,CA,34.3488,-119.3304,23.216.10.54 +US,HILLSBOROUGH,NJ,40.4995,-74.629,184.26.44.38 +US,PRYOR,OK,36.2697,-95.3138,165.254.138.165 +US,LAKEZURICH,IL,42.2010,-88.0504,107.14.38.224 +US,LAPLACE,LA,30.1499,-90.4621,184.84.180.68 +US,FEASTERVILLETREVOSE,PA,40.1496,-74.9856,23.67.242.139 +US,YONKERS,NY,40.9431,-73.8809,184.51.125.68 +US,BENTONHARBOR,MI,42.1150,-86.3578,96.17.9.8 +GB,CARDIFF,WA,51.50,-3.20,184.27.139.24 +US,BLUERIDGE,GA,34.7762,-84.2671,184.28.127.55 +US,BREMERTON,WA,47.5964,-122.6209,23.212.59.85 +IN,RAJAHMUNDRY,AP,16.98,81.78,23.57.69.157 +US,HACKETTSTOWN,NJ,40.8661,-74.8361,184.26.44.38 +US,SANFERNANDO,CA,34.2870,-118.435,184.50.26.179 +US,ODELL,OR,45.5565,-121.4733,184.27.179.187 +US,TWINFALLS,ID,42.2444,-114.6624,192.80.13.108 +SR,PARAMARIBO,"",5.83,-55.17,23.74.2.12 +RU,STAVROPOL,"",53.52,49.41,2.21.240.40 +US,SEFFNER,FL,27.9906,-82.2811,23.33.186.101 +AM,EREVAN,"",40.18,44.50,80.239.237.230 +CN,WUZHOU,GX,23.48,111.32,192.80.13.108 +IT,BOLOGNA,"",44.48,11.33,2.18.240.95 +US,PAWTUCKET,RI,41.8706,-71.3891,72.246.43.237 +JP,TAISEI,17,36.45,136.47,23.3.104.16 +IT,ALESSANDRIA,"",44.90,8.62,195.22.200.243 +GB,BAGULEY,EN,53.38,-2.25,88.221.87.112 +US,SAINTJOHNS,AZ,34.4981,-109.2419,184.85.249.14 +US,ATASCADERO,CA,35.4482,-120.6696,23.216.10.54 +DE,HAU,NW,51.15,6.27,23.14.94.220 +US,SHELBYVILLE,TN,35.4645,-86.4889,23.79.240.36 +CA,SCARBOROUGH,ON,43.75,-79.20,192.204.11.226 +US,GENESEO,NY,42.7919,-77.7757,107.14.38.217 +US,PERRYSBURG,OH,41.5209,-83.5671,23.74.8.8 +US,SANTANVALLEY,AZ,33.3064,-111.8406,23.5.164.143 +DE,HAUPT,NW,51.80,8.62,2.20.142.166 +DE,SCHWEDT,BB,53.07,14.30,92.122.207.164 +TZ,DARESSALAAM,"",-6.80,39.28,92.122.127.109 +FR,CHAMBERY,"",45.57,5.93,88.221.83.122 +US,SPARTA,IL,38.1133,-89.7153,23.63.227.227 +CA,GRANDEPRAIRIE,AB,55.17,-118.80,184.27.179.165 +US,STURGEONBAY,WI,44.7888,-87.4464,184.85.215.165 +US,SALINAS,CA,36.6625,-121.6487,69.22.154.219 +JP,OKINAWA,47,26.34,127.80,184.51.199.145 +US,WHITEFISH,MT,48.5029,-114.5829,107.14.32.228 +BR,BARRAMANSA,RJ,-22.53,-44.18,200.174.107.50 +US,NAMPA,ID,43.5891,-116.6159,192.80.13.108 +MX,MORELIA,MIC,19.70,-101.12,23.215.15.22 +US,ADRIAN,MI,41.9076,-84.0644,165.254.207.111 +US,BOAZ,AL,34.2012,-86.1667,23.79.240.36 +US,GARLAND,TX,32.9284,-96.6206,23.215.15.22 +PH,PAMPANGA,"",15.18,120.54,23.2.16.104 +CZ,KARVINA,"",49.87,18.55,23.74.24.69 +US,SAVANNAH,GA,32.0721,-81.0952,72.246.247.5 +US,PAMPA,TX,35.4253,-100.8386,23.215.15.9 +HN,TEGUCIGALPA,"",14.10,-87.22,165.254.205.13 +US,NEWTON,KS,38.0076,-97.2953,23.215.15.9 +CA,MONTROYAL,QC,45.52,-73.65,72.246.43.232 +DK,AALBORG,"",57.05,9.93,213.155.156.206 +AT,SCHWARZACH,"",47.45,9.75,2.16.217.206 +PL,GORZOW,"",51.03,18.43,80.239.222.169 +US,OFALLON,MO,38.8357,-90.7206,96.17.14.16 +US,KENT,WA,47.3814,-122.2339,184.84.180.101 +US,WANTAGH,NY,40.6810,-73.5104,184.26.44.38 +US,UNIONTOWN,PA,39.8676,-79.7351,184.28.17.76 +US,BROKENBOW,OK,34.0533,-94.7758,23.215.15.32 +US,RAMSEY,NJ,41.0594,-74.1457,184.51.125.68 +US,FRAZIERPARK,CA,34.9441,-119.1553,184.50.26.201 +US,YPSILANTI,MI,42.1967,-83.6251,23.63.227.227 +MP,SAIPAN,"",16.0000,145.5003,63.243.241.248 +US,MACCLENNY,FL,30.2647,-82.1181,23.79.240.37 +ID,TIME,"",0.15,101.25,23.15.10.106 +BG,VARNA,"",43.22,27.92,23.62.237.133 +US,OILCITY,PA,41.4798,-79.6741,165.254.144.25 +DK,EJBY,"",55.43,9.95,213.155.156.207 +US,HUDSON,OH,41.2467,-81.4522,63.216.54.236 +AL,TIRANA,"",41.33,19.82,85.205.31.88 +US,ANNISTON,AL,33.6763,-85.9351,72.246.65.37 +IT,ANCONA,"",43.63,13.50,193.45.15.198 +US,CABERY,IL,40.9777,-88.1923,65.113.249.11 +CH,REINACH,"",47.27,8.18,23.14.94.224 +US,NEWTOWN,PA,40.2672,-74.9516,184.26.44.38 +US,CRESCENTCITY,CA,41.7011,-123.7874,184.27.179.181 +US,COUNTRYCLUBHILLS,IL,41.5589,-87.7259,23.67.60.223 +US,NASHUA,NH,42.7370,-71.4488,23.67.244.248 +US,CAMDEN,NJ,39.9258,-75.12,23.67.242.156 +US,SHARPSBURG,GA,33.3810,-84.6468,23.79.240.36 +JP,OITA,44,33.24,131.61,23.15.1.67 +CN,JINHUA,ZJ,29.12,119.65,72.246.191.19 +US,SPRINGVALLEY,CA,32.7449,-116.9981,23.216.10.78 +US,LAVERNE,CA,34.1693,-117.7375,107.14.44.185 +US,PACIFIC,WA,47.2721,-122.2428,23.212.59.63 +DZ,OUARGLA,"",31.96,5.33,79.140.94.254 +AU,LOWERPLENTY,VIC,-37.73,145.12,184.84.221.116 +CO,PEREIRA,"",4.82,-75.70,23.74.2.12 +CA,CORNWALL,ON,45.02,-74.73,67.69.197.95 +DE,WEINBACH,HE,50.43,8.30,195.145.147.101 +US,LAKEVILLA,IL,42.4132,-88.0615,23.67.60.217 +US,AVONDALE,AZ,33.4440,-112.3152,184.50.26.179 +TC,GRANDTURK,"",21.47,-71.13,23.74.2.7 +NO,HALDEN,"",59.15,11.38,2.21.240.61 +IN,ERNAKULAM,KL,9.98,76.28,2.21.240.40 +CA,MOOSEJAW,SK,50.40,-105.55,184.150.187.229 +DZ,ALGER,"",36.76,3.05,79.140.94.254 +US,HARTWELL,GA,34.3416,-82.926,23.79.240.36 +RU,ASTRAKHAN,"",57.82,51.26,2.21.240.40 +US,GLENNVILLE,GA,31.9485,-81.9795,63.216.54.231 +AU,ARTARMON,NSW,-33.82,151.18,23.62.8.21 +US,MISSIONHILLS,CA,34.2663,-118.4599,184.50.26.179 +US,WAYNESBORO,VA,38.0936,-78.8951,184.26.44.40 +US,NOVATO,CA,38.1262,-122.559,23.61.195.165 +US,MARSHALL,MO,39.0733,-93.1988,23.215.15.9 +US,ALTOONA,PA,40.5542,-78.4349,184.28.17.55 +DE,ESSEN,NW,51.45,7.02,80.157.170.154 +US,LOMBARD,IL,41.8742,-88.0172,23.67.60.220 +GB,GLOUCESTER,EN,51.83,-2.25,95.101.2.122 +US,NATICK,MA,42.2868,-71.3531,23.67.242.139 +US,ENGLISHTOWN,NJ,40.2769,-74.3692,184.26.44.38 +US,FRESHMEADOWS,NY,40.7391,-73.7931,184.26.44.42 +CA,BARRIE,ON,44.38,-79.70,209.148.192.61 +PT,PORTO,"",41.15,-8.62,212.113.165.106 +US,BRIDGEWATER,NJ,40.5945,-74.6244,184.26.44.38 +US,ALVIN,TX,29.4018,-95.2649,23.212.53.64 +US,INOLA,OK,36.1597,-95.5177,23.74.8.8 +US,JUPITER,FL,26.9429,-80.1337,184.25.157.155 +CO,MEDELLIN,"",6.25,-75.58,23.74.2.12 +US,TRAVERSECITY,MI,44.7515,-85.6942,23.63.227.214 +US,LIBBY,MT,48.3326,-115.3444,184.27.179.179 +BO,SANTACRUZDELASIERRA,"",-17.80,-63.17,200.91.22.125 +US,SOMERSET,KY,37.0813,-84.4741,107.14.38.227 +AU,FRANKSTON,VIC,-38.13,145.12,165.254.45.32 +US,ROCKINGHAM,NC,34.9229,-79.8048,209.18.41.23 +US,SALISBURY,MD,38.3511,-75.5976,23.192.161.16 +US,SCARSDALE,NY,40.9890,-73.793,184.51.125.79 +US,BELAIR,MD,39.5372,-76.3514,23.192.161.16 +US,RIORANCHO,NM,35.2441,-106.7528,63.226.34.173 +UA,POLTAVA,"",49.58,34.57,92.122.215.67 +IR,FARS,"",35.18,59.38,96.17.182.130 +US,PANAMACITYBEACH,FL,30.2113,-85.7957,23.79.240.48 +CZ,OSTRAVA,"",49.83,18.28,23.62.237.138 +US,ABBEVILLE,SC,34.1653,-82.3751,204.2.243.143 +US,GAS,KS,37.9244,-95.3395,23.77.234.11 +US,GULFPORT,MS,30.3896,-89.0988,23.212.53.75 +DE,DUISBURG,NW,51.43,6.75,80.157.170.221 +US,LEAKESVILLE,MS,31.1153,-88.5168,184.51.35.226 +UA,KYYIV,"",50.43,30.52,92.122.215.89 +AU,BLACKTOWN,NSW,-33.77,150.92,23.62.8.25 +PH,CEBU,"",10.31,123.89,202.78.83.175 +US,BARTLESVILLE,OK,36.7524,-96.0733,63.235.21.140 +US,WOBURN,MA,42.4867,-71.1543,184.25.109.196 +ID,CIREBON,"",-6.73,108.57,118.98.37.103 +US,COCOA,FL,28.3696,-80.7478,184.51.145.7 +US,CASAGRANDE,AZ,32.8794,-111.7568,184.50.26.201 +US,MARKSVILLE,LA,31.1750,-91.9985,96.17.153.162 +RU,DELTA,"",46.64,48.05,2.22.52.105 +IN,PATNA,KA,12.77,74.87,96.17.182.136 +US,HELENA,MT,46.5543,-112.1629,165.254.1.206 +US,MCALLEN,TX,26.2183,-98.2399,184.26.93.111 +CA,ESTEVAN,SK,49.15,-103.00,184.150.187.229 +IT,PESCARA,"",42.75,13.27,95.101.34.105 +SE,LULEA,BD,65.58,22.15,82.96.58.102 +RU,SEVEROKURILSK,"",50.68,156.12,96.7.251.97 +JP,OKAYAMA,33,34.65,133.92,202.229.2.213 +US,PALATKA,FL,29.7389,-81.6715,23.79.240.36 +US,WESTCHICAGO,IL,41.9000,-88.2142,107.14.38.217 +RO,RESITA,"",45.30,21.90,81.196.26.237 +US,CROSSVILLE,TN,35.9347,-85.0211,23.215.15.9 +US,YORBALINDA,CA,33.8876,-117.8023,184.87.195.109 +US,SYKESVILLE,MD,39.3995,-76.9748,23.192.161.21 +US,HANA,HI,20.7422,-156.1196,23.216.10.78 +US,NEWPALTZ,NY,41.7512,-74.0601,24.143.199.156 +GB,POOLE,EN,50.72,-2.00,23.67.255.106 +RO,IASI,"",45.77,24.93,81.196.26.231 +US,SOUTHHOLLAND,IL,41.5964,-87.6014,107.14.38.217 +US,WARRENTON,VA,38.6876,-77.819,184.26.44.42 +US,GILMER,TX,32.7226,-94.9896,23.212.53.64 +US,CHOCTAW,OK,35.4577,-97.2616,23.74.8.8 +IN,MANGALORE,KA,12.86,74.84,23.57.76.20 +US,WALLINGTON,NJ,40.8534,-74.1065,23.67.242.139 +AT,WEISSACH,"",47.47,12.52,195.145.147.101 +US,MABLETON,GA,33.8161,-84.553,23.212.53.64 +CR,HEREDIA,"",10.00,-84.12,23.215.15.22 +US,OTTUMWA,IA,41.0803,-92.3054,65.113.249.8 +US,VERMILION,OH,41.3884,-82.3643,107.14.38.217 +HU,GYOR,"",47.68,17.63,23.14.94.220 +IN,PATEL,JK,32.98,74.86,23.57.69.157 +JE,SAINTHELIER,"",49.18,-2.10,195.59.54.141 +AU,ASHFIELD,NSW,-33.88,151.12,165.254.45.13 +US,FORESTHILLS,NY,40.7228,-73.845,24.143.199.188 +SA,LINE,"",28.76,43.74,79.140.94.243 +IN,LUCKNOW,UP,26.85,80.92,23.57.69.156 +US,SUNBURY,OH,40.2799,-82.849,107.14.38.217 +CA,LABAIE,QC,48.33,-70.87,67.69.197.92 +US,SARANACLAKE,NY,44.3202,-74.2149,107.14.38.227 +KZ,TALDYKORGAN,"",45.02,78.37,23.14.94.224 +US,CATONSVILLE,MD,39.2711,-76.7461,23.192.161.21 +US,DAMASCUS,MD,39.2916,-77.2137,184.27.45.150 +AR,SANMIGUEL,"",-34.52,-58.78,200.123.201.219 +JP,YAMAGATA,06,38.25,140.34,202.229.2.212 +US,NORTHPORT,FL,27.0874,-82.2022,192.204.11.226 +RU,SARATOV,"",51.57,46.03,2.21.240.61 +GH,ACCRA,"",5.55,-0.22,23.212.108.28 +US,FAIRBURN,GA,33.5864,-84.6255,23.79.240.37 +CZ,BRNO,"",49.20,16.63,23.62.237.135 +US,ELSOBRANTE,CA,37.9619,-122.283,96.17.12.48 +US,STEPHENVILLE,TX,32.2465,-98.2492,23.215.15.22 +US,SYCAMORE,IL,42.0146,-88.6891,23.67.60.223 +US,WOODLANDHILLS,CA,34.1552,-118.5942,184.50.26.179 +BR,CANOAS,MG,-21.42,-46.97,187.59.4.154 +IL,PETACHTIKVAH,"",32.09,34.87,212.25.69.142 +US,MURRELLSINLET,SC,33.5501,-79.0592,69.31.132.226 +US,COLONIALHEIGHTS,VA,37.2887,-77.3954,184.28.17.76 +US,HOPKINS,MN,44.9540,-93.4312,165.254.96.242 +GB,WALTON,EN,51.38,-0.43,23.67.255.158 +US,DEXTER,MO,36.7491,-89.9236,184.28.17.55 +US,MARICOPA,AZ,33.0567,-112.0467,63.226.34.176 +US,WESTHILLS,CA,34.2068,-118.6798,184.50.26.179 +US,HILLSDALE,MI,41.8825,-84.6162,23.67.60.223 +CZ,LIBEREC,"",50.76,15.07,92.122.189.85 +BR,NATAL,RN,-5.78,-35.22,190.98.142.115 +PK,WAN,"",32.42,71.69,23.75.23.140 +RO,CRAIOVA,"",44.32,23.80,81.196.26.231 +US,HARTVILLE,OH,40.9665,-81.3038,107.14.38.217 +US,BEAVER,WV,37.7672,-81.0206,184.28.17.76 +US,BOLINGBROOK,IL,41.6956,-88.0759,23.67.60.223 +US,LYNBROOK,NY,40.6573,-73.674,23.67.242.139 +HU,DUNAUJVAROS,"",46.98,18.93,23.14.94.220 +TR,INCESU,"",39.92,32.88,193.45.15.198 +CA,SELKIRK,MB,50.15,-96.88,23.74.8.8 +US,HOWE,IN,41.7293,-85.4292,205.185.195.170 +US,CHERRYHILL,NJ,39.9312,-75.0244,23.67.242.139 +JP,TSUKUBA,08,36.08,140.12,23.15.1.55 +US,ALLENDALE,MI,42.9767,-85.9382,165.254.207.111 +SE,NORRKOPING,E,58.60,16.18,213.155.156.207 +US,OMAK,WA,48.4274,-119.5241,184.27.179.159 +US,ESCALON,CA,37.8207,-121.0167,96.17.12.48 +US,RIDGEWOOD,NY,40.7008,-73.8892,24.143.199.156 +US,RESEDA,CA,34.2011,-118.5406,184.50.26.204 +ID,BANJARMASIN,"",-4.75,104.55,23.0.162.54 +US,SEABROOK,TX,29.5802,-95.0274,23.212.53.75 +BR,PALMAS,TO,-10.42,-48.44,189.72.175.118 +US,CANONCITY,CO,38.5330,-105.3899,107.14.32.235 +US,CALDWELL,TX,30.5405,-96.7258,23.215.15.22 +FR,REST,"",47.92,-4.20,77.67.27.250 +MX,CAMPECHE,CAM,19.85,-90.53,23.212.53.75 +US,NORRISTOWN,PA,40.1271,-75.3202,184.26.44.38 +JP,GIFU,21,35.42,136.75,117.104.139.136 +US,KERNERSVILLE,NC,36.1188,-80.075,209.18.41.23 +US,POUGHKEEPSIE,NY,41.7144,-73.9069,184.26.44.42 +US,EULESS,TX,32.8604,-97.0691,213.155.156.206 +US,FOUNTAINHILLS,AZ,33.5988,-111.7413,184.50.26.204 +US,REIDSVILLE,NC,36.3355,-79.6561,209.18.41.27 +PL,BYDGOSZCZ,"",53.15,18.00,2.22.52.101 +US,WAXAHACHIE,TX,32.3150,-96.7926,96.16.7.101 +US,WIGGINS,MS,30.8678,-89.1157,96.17.153.162 +RE,LEPORT,"",-20.92,55.30,81.52.201.77 +US,DERRY,NH,42.8895,-71.2818,184.25.109.200 +BO,COCHABAMBA,"",-17.38,-66.15,72.246.65.26 +PL,KOSZALIN,"",54.20,16.18,2.22.52.101 +US,MUKWONAGO,WI,42.8738,-88.3526,107.14.38.218 +DE,SCHWERIN,MV,53.63,11.38,80.157.170.221 +LA,VIENTIANE,"",17.97,102.60,23.61.195.149 +JP,OMIHACHIMAN,25,35.14,136.08,202.229.2.227 +US,AUBURNDALE,FL,28.0903,-81.8298,23.33.186.101 +CA,VERDUN,QC,45.45,-73.57,204.93.33.141 +HU,KISVARDA,"",48.22,22.08,80.239.222.167 +LY,TRIPOLI,"",32.89,13.18,79.140.94.234 +US,BELLFLOWER,CA,33.8879,-118.1274,23.216.10.54 +US,REISTERSTOWN,MD,39.4886,-76.8057,23.192.161.21 +US,KEYWEST,FL,24.5796,-81.6849,23.79.240.48 +ID,TIMUR,"",-8.18,131.08,96.17.180.166 +US,MUNFORDVILLE,KY,37.3145,-85.9322,23.220.100.223 +US,WATERVLIET,NY,42.7341,-73.7188,23.215.15.9 +US,PARKCITY,UT,40.6558,-111.5034,23.61.195.165 +US,PORTALES,NM,34.1669,-103.2665,96.17.177.63 +US,COLLEGEVILLE,PA,40.1903,-75.4384,184.26.44.38 +US,SOUTHLAKETAHOE,CA,38.8829,-120.0344,23.216.10.54 +VE,MERIDA,"",8.60,-71.14,23.74.2.7 +US,LADERARANCH,CA,33.5682,-117.6365,184.50.26.194 +US,GAFFNEY,SC,35.0161,-81.6141,23.79.240.36 +US,LAMARQUE,TX,29.3673,-94.9891,23.212.53.75 +VG,ROADTOWN,"",18.42,-64.62,23.33.186.134 +RU,ARKHANGELSK,"",55.48,36.40,2.21.240.61 +ZM,LUSAKA,"",-15.42,28.28,41.193.163.53 +US,CYPRESS,TX,29.9695,-95.6976,96.17.163.165 +US,PURCELLVILLE,VA,39.1720,-77.7306,184.27.45.150 +US,PITTSFIELD,MA,42.4608,-73.282,107.14.38.218 +HU,SZOLNOK,"",47.18,20.20,23.62.237.135 +US,BRODHEADSVILLE,PA,40.9370,-75.4125,184.26.44.40 +IN,KALYAN,MH,19.25,73.15,23.211.135.66 +DK,BALLERUP,"",55.73,12.37,23.65.29.106 +US,ARVADA,CO,39.8028,-105.0869,63.235.21.147 +US,SAINTCLAIRSHORES,MI,42.4633,-82.9002,23.67.60.220 +KR,ILSAN,"",38.18,127.82,125.56.214.147 +US,LOGANSPORT,IN,40.8028,-86.3678,23.67.60.222 +US,CHARLEVOIX,MI,45.2393,-85.3038,23.63.227.214 +ID,BANDUNG,"",-6.90,107.60,23.0.162.54 +US,LOGANVILLE,GA,33.8218,-83.8917,72.246.65.23 +US,MACUNGIE,PA,40.5204,-75.5692,184.26.44.38 +US,SANDSPRINGS,OK,36.1933,-96.1589,165.254.137.75 +US,BALDWIN,NY,40.6539,-73.609,23.67.242.139 +US,SANDIMAS,CA,34.1088,-117.8082,23.216.10.78 +NZ,PAPATOETOE,"",-36.98,174.85,219.88.186.164 +FI,OULU,"",65.02,25.47,2.21.240.40 +DE,HERZOGENAURACH,BY,49.55,10.88,84.53.146.39 +CN,CHANGZHOU,JS,31.78,119.97,184.50.87.178 +US,JERSEYSHORE,PA,41.4260,-77.4189,23.192.161.21 +US,GROVES,TX,29.9495,-93.9207,107.14.36.199 +CA,YORKTON,SK,51.22,-102.47,184.150.187.229 +US,SARATOGASPRINGS,NY,43.0842,-73.7411,209.18.41.23 +US,BUFFALOGROVE,IL,42.1650,-87.9695,107.14.38.218 +BR,FOZDOIGUACU,PR,-25.55,-54.58,187.59.4.147 +US,KILMARNOCK,VA,37.7427,-76.3858,208.185.55.117 +US,CUSTER,SD,43.6653,-103.7669,23.63.227.227 +US,KEWANEE,IL,41.2504,-89.9568,23.67.60.220 +RO,SLATINA,"",44.43,24.37,81.196.26.236 +US,ELIZABETHTOWN,KY,37.7021,-85.8419,23.220.100.223 +US,ROBERT,LA,30.5167,-90.3282,96.17.153.157 +US,CALEXICO,CA,32.6882,-115.5488,23.215.15.9 +JP,MITO,08,36.37,140.47,72.246.191.19 +DE,WIESBADEN,HE,50.08,8.25,23.14.94.228 +US,ORION,IL,41.3669,-90.3966,23.74.8.8 +NO,GREAKER,"",59.27,11.03,213.155.156.212 +CR,SANPEDRO,"",9.93,-84.05,72.164.253.83 +US,CASTROVILLE,TX,29.3805,-98.9015,107.14.43.29 +US,ABINGDON,VA,36.7393,-82.0092,23.67.60.222 +US,MILLBURN,NJ,40.7229,-74.3006,23.67.242.156 +CA,QUEBEC,QC,46.80,-71.25,67.69.197.95 +US,PALOSHILLS,IL,41.7012,-87.8574,23.67.60.217 +US,GLENROSE,TX,32.2052,-97.8091,205.185.195.170 +US,CHENEY,WA,47.4110,-117.6288,206.104.149.133 +US,FRISCO,TX,33.1507,-96.8235,184.28.23.4 +US,ARTESIA,CA,33.8679,-118.081,23.216.10.78 +US,ROCKLEDGE,FL,28.2781,-80.7792,23.34.56.147 +US,SCRANTON,PA,41.4088,-75.6626,23.192.161.21 +BR,CASCAVEL,PR,-24.95,-53.47,187.59.4.154 +US,NEWIBERIA,LA,29.9366,-91.8695,96.17.153.157 +US,ARMONK,NY,41.1347,-73.7005,23.67.242.139 +US,FORTMILL,SC,35.0493,-80.9623,184.51.35.226 +US,READING,PA,40.3659,-75.9566,23.192.161.16 +US,MATTOON,IL,39.5101,-88.3823,205.185.195.170 +RU,VOLGA,"",57.95,38.40,213.200.109.183 +NO,DRAMMEN,"",59.74,10.21,213.155.156.212 +US,ELSEGUNDO,CA,33.9182,-118.4042,184.50.26.179 +US,EGYPT,TX,29.4044,-96.2367,23.212.53.64 +IR,KARAJ,"",35.72,51.11,96.17.182.136 +NZ,PALMERSTONNORTH,"",-40.35,175.62,219.88.186.167 +ID,MAGELANG,"",-7.47,110.22,23.0.162.46 +US,EAGLEMOUNTAIN,UT,40.3099,-111.9316,184.50.26.179 +US,BULVERDE,TX,29.7881,-98.4616,184.26.93.116 +CH,SANKTGALLEN,"",47.47,9.40,193.247.167.214 +IN,RAJKOT,GJ,22.30,70.78,23.211.135.66 +US,SAVAGE,MN,44.7628,-93.362,204.93.47.216 +US,ALTADENA,CA,34.1951,-118.14,63.217.232.17 +RO,BACAU,"",46.57,26.90,81.196.26.231 +DE,MAUER,BW,49.34,8.80,195.95.193.147 +PL,LECZNA,"",52.42,20.72,2.22.52.109 +CZ,TEPLICE,"",50.63,13.83,23.74.24.66 +US,HILLAFB,UT,41.1284,-111.9912,184.84.180.98 +US,SPRINGTOWN,TX,32.9715,-97.6513,23.212.53.64 +US,ROSELLE,NJ,40.6527,-74.2601,184.26.44.38 +SE,LYCKSELE,AC,64.60,18.67,2.21.240.61 +VN,QUANGTRUNG,"",20.70,105.37,23.76.205.111 +US,CERRITOS,CA,33.8673,-118.0676,184.50.26.194 +US,BETHLEHEM,PA,40.5862,-75.372,184.27.45.150 +US,PRICE,UT,39.5589,-110.9112,23.215.15.9 +US,OAKRIDGE,NC,36.1724,-79.9835,209.18.41.27 +FR,BELFORT,"",47.63,6.87,2.16.117.200 +US,LEHIGHACRES,FL,26.5583,-81.6174,23.212.53.75 +US,HESPERIA,CA,34.4264,-117.3001,23.216.10.54 +US,PENNSVILLE,NJ,39.6375,-75.5059,23.192.161.30 +IT,RIPESANGINESIO,"",43.15,13.37,95.101.34.109 +FR,LESMINIMES,"",43.62,1.43,2.16.117.185 +US,LAPUENTE,CA,34.0289,-117.9371,23.216.10.78 +MY,SABAH,"",3.77,100.98,203.106.85.4 +US,SUNVALLEY,CA,34.2294,-118.357,63.233.112.196 +US,PLAYADELREY,CA,33.9505,-118.4382,23.216.10.54 +CA,DUNCAN,BC,48.78,-123.70,184.27.179.159 +US,MAPLEHEIGHTS,OH,41.4092,-81.5624,96.17.9.14 +GB,GUILDFORD,EN,51.22,-0.57,88.221.87.94 +TH,PAKKRED,"",13.92,100.50,110.164.11.181 +US,ELCAMPO,TX,29.1916,-96.2212,184.28.23.24 +US,ROWLETT,TX,32.9026,-96.5636,23.5.164.143 +US,WOODVILLE,TX,30.7643,-94.4448,65.116.149.89 +US,OLIVEHURST,CA,39.0904,-121.5521,23.212.52.79 +CA,LENNOXVILLE,QC,45.37,-71.87,72.246.43.215 +US,WINFIELD,WV,38.5058,-81.9328,184.27.45.150 +US,MAHWAH,NJ,41.0818,-74.1862,165.254.35.182 +US,RAMONA,CA,33.0538,-116.8517,173.223.52.67 +US,REHOBOTH,MA,41.8440,-71.246,184.25.109.200 +US,MANISTIQUE,MI,46.1571,-86.3397,184.85.215.170 +US,LARGO,FL,27.9154,-82.8023,192.204.82.239 +ES,BASAURI,"",43.02,-2.40,92.122.188.161 +US,WALLAWALLA,WA,46.1270,-118.3596,184.27.179.187 +US,SCOTTSVILLE,KY,36.7794,-86.196,63.216.54.236 +US,MANASSAS,VA,38.7657,-77.4852,23.192.161.16 +IN,GOLD,JK,33.59,74.14,96.17.182.130 +US,SANMARINO,CA,34.1223,-118.1135,23.215.15.9 +SE,SOLNA,AB,59.37,18.02,2.21.240.40 +BG,PERNIK,"",42.60,23.03,2.20.45.104 +JP,HIROSHIMA,34,34.40,132.45,23.3.74.113 +GB,EDINBURGH,SC,55.95,-3.20,88.221.87.94 +MX,NUEVOLAREDO,TAM,27.50,-99.52,23.5.164.146 +US,GLENWOOD,IA,41.0322,-95.6979,23.77.234.11 +US,THECOLONY,TX,33.0886,-96.9013,184.28.23.24 +HU,GODOLLO,"",47.60,19.37,23.14.94.220 +US,LLANO,TX,30.6126,-98.6923,23.215.15.9 +US,NEWALBANY,IN,38.2909,-85.8472,23.220.100.224 +US,THOUSANDOAKS,CA,34.1707,-118.8364,184.50.26.179 +US,DECATUR,IL,39.8055,-88.9128,23.67.60.220 +CR,ALAJUELA,"",10.02,-84.22,23.74.2.12 +US,HOLLAND,MI,42.7878,-86.1086,23.63.227.223 +BS,NASSAU,"",25.08,-77.35,72.164.253.83 +SE,VASTERAS,U,59.62,16.55,2.21.240.61 +RO,SLOBOZIA,"",44.38,25.93,72.246.43.237 +US,BARTONSVILLE,PA,41.0176,-75.2939,204.94.155.231 +GB,BRADFORD,EN,53.78,-1.75,88.221.87.94 +US,WHITESBURG,KY,37.1283,-82.8498,63.151.29.12 +US,STEVENSPOINT,WI,44.5531,-89.5186,65.113.249.11 +US,MILLBRAE,CA,37.5972,-122.4192,96.17.12.44 +VU,PORTVILA,"",-17.73,168.32,23.62.8.25 +US,ROCKWELL,NC,35.5293,-80.4409,209.18.41.27 +US,JEMISON,AL,32.9898,-86.6799,184.51.35.215 +US,EDENPRAIRIE,MN,44.8655,-93.4304,23.215.15.22 +NO,MANGER,"",60.77,5.35,213.155.156.212 +US,MCCALLA,AL,33.3452,-87.0035,23.220.100.224 +CG,BRAZZAVILLE,"",-4.26,15.28,95.101.34.109 +US,EDINBORO,PA,41.8735,-80.1661,184.26.44.38 +US,WOODDALE,IL,41.9645,-87.9808,23.67.60.220 +US,ENCINITAS,CA,33.0368,-117.2914,63.235.21.147 +US,ERLANGER,KY,39.0170,-84.607,184.51.147.33 +US,LYNCHBURG,VA,37.3527,-79.1576,184.27.45.157 +US,LULING,TX,29.6952,-97.6509,107.14.36.199 +US,PRATTVILLE,AL,32.4989,-86.4129,64.86.201.121 +US,CULLMAN,AL,34.1748,-86.8225,23.5.164.143 +US,WHITEPLAINS,NY,41.0328,-73.7651,184.51.125.79 +US,WILDWOOD,NJ,38.9808,-74.8281,184.26.44.38 +EE,PARNU,"",58.37,24.51,2.21.240.40 +US,PRAIRIEDUSAC,WI,43.3094,-89.8029,184.85.215.170 +US,CHARLTONHEIGHTS,WV,38.1238,-81.2342,184.28.17.76 +US,GREENVALLEY,AZ,31.8307,-111.0345,63.226.34.174 +US,EATONTOWN,NJ,40.2996,-74.074,23.212.53.64 +US,HYANNIS,MA,41.6607,-70.2924,184.25.109.196 +US,BRAWLEY,CA,32.9870,-115.4637,63.235.21.141 +TR,SABANCI,"",37.48,39.35,2.20.142.166 +US,BROWNWOOD,TX,31.6193,-98.9922,23.215.15.22 +AT,MICHELDORF,"",47.87,14.13,46.33.70.104 +US,DAHLONEGA,GA,34.5608,-84.0088,63.216.54.216 +DE,MANHEIM,NW,50.88,6.60,23.14.94.224 +US,ESTHERVILLE,IA,43.3937,-94.7541,65.113.249.8 +TW,SHOUFENG,"",23.87,121.50,61.220.62.171 +US,LOCKHART,TX,29.8965,-97.6713,107.14.36.199 +US,RADFORD,VA,37.1746,-80.6425,96.6.47.106 +IN,SIKKA,GJ,22.43,69.83,23.57.69.157 +KZ,PETROPAVLOVSK,"",54.88,69.16,23.14.94.228 +US,KAYSVILLE,UT,41.0365,-111.927,23.61.195.166 +US,PONTIAC,MI,42.6705,-83.292,23.67.60.222 +US,FRAMINGHAM,MA,42.3203,-71.4404,184.29.107.20 +CA,AJAX,ON,43.85,-79.02,72.246.43.215 +US,HAYDEN,ID,47.7955,-116.5418,184.27.179.181 +US,VALLEJO,CA,38.1438,-122.2502,23.61.195.165 +FR,CROIX,"",49.80,2.98,95.100.171.16 +US,DELRIO,TX,29.8301,-100.8984,107.14.36.199 +KH,PREAH,"",13.60,105.07,23.76.205.111 +RU,KEMEROVO,"",55.33,86.08,2.21.240.61 +VN,DONGNAI,"",18.10,106.33,23.5.165.167 +MG,ANTANANARIVO,"",-18.92,47.52,81.52.201.98 +US,ETTERS,PA,40.1451,-76.7914,23.192.161.16 +US,MATHIS,TX,28.0654,-97.7489,184.26.93.111 +US,VALDESE,NC,35.7374,-81.5644,184.27.45.157 +GB,MIDDLESBROUGH,EN,54.57,-1.16,88.221.87.94 +RU,VLADIMIR,"",56.14,40.40,217.212.227.25 +FR,SUCYENBRIE,"",48.77,2.53,2.16.117.190 +US,RIDGEFIELDPARK,NJ,40.8547,-74.0203,23.67.242.139 +US,SURPRISE,AZ,33.6321,-112.3824,184.50.26.185 +US,BROOKFIELD,WI,43.0627,-88.099,107.14.38.227 +AU,SAINTLUCIA,QLD,-27.50,153.00,23.62.157.31 +US,MOUNTSTERLING,KY,38.0657,-83.9424,23.61.195.163 +US,BURNSVILLE,MN,44.7310,-93.293,23.67.60.222 +BA,ZENICA,"",43.89,18.31,23.14.94.220 +US,FLOURTOWN,PA,40.1083,-75.2168,184.27.45.157 +CA,PETERBOROUGH,ON,44.30,-78.33,72.246.43.237 +RU,BELGOROD,"",52.87,34.65,2.21.240.40 +US,LUTHERVILLETIMONIUM,MD,39.4394,-76.6555,23.192.161.21 +US,PORTMURRAY,NJ,40.7953,-74.9091,23.192.161.16 +ID,JEMBER,"",-8.17,113.70,23.0.162.54 +US,LIBERTY,NY,41.7928,-74.7401,184.26.44.42 +US,CUSHING,OK,35.9968,-96.7376,184.28.23.24 +AT,ENNSDORF,"",48.20,14.48,46.33.70.97 +GR,KOMOTINI,"",41.12,25.40,80.157.169.18 +US,ESSEXJUNCTION,VT,44.5358,-73.0548,184.25.109.200 +US,OCALA,FL,29.2239,-82.088,184.51.35.226 +US,ALMA,MI,43.3819,-84.6786,23.63.227.227 +US,PORTLAVACA,TX,28.5342,-96.663,23.215.15.9 +HU,GOD,"",47.70,19.13,23.14.94.220 +US,NORTHHIGHLANDS,CA,38.6687,-121.3891,96.17.12.48 +US,TUNKHANNOCK,PA,41.5722,-75.9275,184.26.44.42 +US,ALLISONPARK,PA,40.5779,-79.9517,184.27.45.157 +US,MONROEVILLE,PA,40.4264,-79.7596,96.6.47.120 +US,PEWAUKEE,WI,43.0807,-88.2675,107.14.38.218 +US,STREAMWOOD,IL,42.0230,-88.1742,23.67.60.220 +US,BATH,NY,42.3460,-77.3478,107.14.38.218 +JP,KOKURYO,13,35.65,139.57,96.7.251.95 +TR,BAHCELIEVLER,"",39.93,32.83,46.33.70.213 +RU,RYAZAN,"",55.67,36.67,213.155.156.212 +US,HORNITOS,CA,37.4864,-120.2361,165.254.144.32 +US,CHANNAHON,IL,41.4089,-88.1749,96.17.14.16 +US,PHILLIPSBURG,NJ,40.7083,-75.1472,23.67.242.139 +US,WINONA,MN,43.9823,-91.6349,184.51.147.6 +US,BASTROP,LA,32.8721,-91.912,23.5.164.143 +US,LEESBURG,FL,28.8097,-81.8939,184.25.157.169 +US,HANFORD,CA,36.2869,-119.6218,23.212.52.88 +DE,LEVERKUSEN,NW,51.03,7.00,92.122.215.67 +IN,ERODE,TN,11.35,77.73,117.239.240.96 +US,NAPOLEON,OH,41.4176,-84.1859,107.14.38.218 +US,KINGMAN,AZ,35.4636,-113.9441,184.85.249.14 +RO,TARGUJIU,"",45.05,23.28,81.196.26.236 +DE,FULDA,HE,50.55,9.67,80.157.150.197 +AU,PORTMELBOURNE,VIC,-37.83,144.93,150.101.152.249 +US,SALINA,KS,38.8424,-97.6193,23.77.234.35 +CH,OERLIKON,"",47.42,8.55,194.25.95.214 +US,FLAGSTAFF,AZ,35.4784,-111.738,24.143.194.216 +ES,MALAGA,"",36.72,-4.42,2.16.1.106 +US,COLLEGEPARK,MD,38.9974,-76.9284,184.27.45.150 +CN,WUXI,JS,31.58,120.29,117.103.188.218 +US,BOYNTONBEACH,FL,26.5253,-80.0668,184.28.184.6 +US,NORTHRICHLANDHILLS,TX,32.8656,-97.2164,23.215.15.22 +US,BLACKWOOD,NJ,39.7780,-75.0552,184.26.44.38 +US,MCHENRY,IL,42.3590,-88.2783,184.27.120.50 +US,DEERPARK,TX,29.7032,-95.1146,23.212.53.75 +US,MARRERO,LA,29.8286,-90.1189,96.17.153.157 +US,LOVINGTON,NM,32.9094,-103.4796,198.172.88.205 +CA,ORANGEVILLE,ON,43.92,-80.08,72.246.43.215 +CN,DONGYING,SD,37.46,118.49,173.223.52.67 +RO,BUZAU,"",45.15,26.83,88.221.93.157 +PK,ISAN,"",31.46,74.01,96.17.182.130 +ES,ALICANTE,"",38.35,-0.48,92.123.73.26 +US,MAYSLANDING,NJ,39.4502,-74.7366,184.26.44.38 +US,LENOIRCITY,TN,35.8295,-84.286,23.79.240.48 +US,AMERY,WI,45.3559,-92.3527,23.63.227.214 +US,SPENCER,MA,42.2477,-71.9927,63.141.200.241 +RU,KAMENSK,"",52.99,32.47,92.122.189.85 +US,GWYNNOAK,MD,39.3248,-76.7203,23.192.161.16 +US,WESTLEBANON,NH,43.6438,-72.295,23.192.161.21 +US,MAGNOLIA,AR,33.2253,-93.2572,23.5.164.143 +IN,MANIPALA,KA,13.35,74.78,23.57.69.159 +US,OSCEOLA,AR,35.6763,-90.0131,173.197.194.159 +US,LORTON,VA,38.6817,-77.2042,23.220.148.108 +US,SANTEE,CA,32.8510,-117.008,184.50.26.204 +US,KINGSTREE,SC,33.7042,-79.7562,209.18.41.23 +US,KERRVILLE,TX,30.0272,-99.1089,184.26.93.116 +US,BAINBRIDGE,GA,30.9045,-84.5727,184.28.127.55 +US,HALFMOONBAY,CA,37.4511,-122.4142,184.85.249.6 +FR,WOERTH,"",48.38,7.63,2.16.117.190 +US,SPANAWAY,WA,47.0761,-122.3963,23.212.59.63 +BR,FLORIANOPOLIS,SC,-27.58,-48.57,187.59.4.154 +ZA,BELLVILLE,"",-33.90,18.63,165.165.46.37 +US,WASHOUGAL,WA,45.6718,-122.2068,184.27.179.159 +US,ROUNDLAKE,IL,42.3442,-88.1158,107.14.38.224 +US,LYNCH,NE,42.8592,-98.4418,204.2.223.90 +US,LONGISLANDCITY,NY,40.7457,-73.9381,24.143.199.188 +US,RIVERVIEW,FL,27.8494,-82.3132,192.204.11.244 +US,SCHOFIELD,WI,44.9014,-89.5403,184.85.215.170 +US,ELYRIA,OH,41.3603,-82.1314,63.216.54.229 +US,GLENSFALLS,NY,43.3117,-73.645,107.14.38.217 +RU,STAR,"",53.62,34.15,80.239.237.84 +DE,WERDAU,SN,50.73,12.38,80.157.150.192 +US,ANKENY,IA,41.7301,-93.5923,23.79.255.149 +US,OWENSCROSSROADS,AL,34.6110,-86.4644,184.51.35.226 +US,ROCKYMOUNT,NC,35.9504,-77.6998,184.28.17.76 +US,HARRISON,OH,39.2734,-84.7476,184.51.147.33 +US,MINERVA,OH,40.7427,-81.0929,107.14.38.224 +US,SAYREVILLE,NJ,40.4595,-74.3616,184.51.125.68 +US,GRANBY,CO,40.0195,-105.8657,184.84.180.68 +US,OCOEE,FL,28.5761,-81.5328,23.34.56.142 +US,THIENSVILLE,WI,43.2173,-87.9347,107.14.38.218 +US,STOUGHTON,WI,42.9244,-89.2046,184.85.215.165 +US,WESTSACRAMENTO,CA,38.5921,-121.5456,23.61.195.149 +US,CALUMETCITY,IL,41.6123,-87.5504,23.67.60.222 +US,CHESWICK,PA,40.5780,-79.8433,23.192.161.21 +US,DUQUOIN,IL,38.0189,-89.2365,23.63.227.214 +PT,CORROIOS,"",38.63,-9.15,195.22.14.133 +US,CAPEGIRARDEAU,MO,37.3091,-89.5732,204.93.47.216 +US,COMBINEDLOCKS,WI,44.2639,-88.309,107.14.38.227 +US,GARDNER,MA,42.5847,-71.987,184.25.109.213 +US,DISTRICTHEIGHTS,MD,38.8541,-76.8832,184.27.45.157 +US,CORDOVA,TN,35.1578,-89.7651,23.79.240.36 +US,HERNANDO,MS,34.8026,-89.9999,23.79.240.48 +IN,BELGAUM,KA,15.87,74.50,23.57.76.18 +US,SELMA,CA,36.5405,-119.6527,23.212.52.88 +ES,SALAMANCA,"",40.97,-5.65,77.67.41.227 +RU,KHABAROVSK,"",48.50,135.10,72.246.184.81 +IN,UDAIPUR,RJ,24.58,73.68,23.205.118.109 +CA,WHITBY,ON,43.87,-78.93,72.246.43.237 +US,TARZANA,CA,34.1585,-118.5493,184.50.26.203 +US,ANDALUSIA,AL,31.2069,-86.6212,63.151.29.12 +RU,KUBAN,"",53.18,35.43,217.212.227.31 +FR,ROUBAIX,"",50.70,3.17,23.212.108.28 +GB,WOLVERHAMPTON,EN,52.58,-2.13,88.221.87.112 +JP,KAITA,31,35.45,133.85,23.3.74.113 +JP,TOYO,38,33.93,133.10,117.104.139.162 +UA,DMITRIY,"",46.65,30.40,80.239.222.167 +US,SALECREEK,TN,35.3979,-85.1221,184.51.35.226 +IN,COIMBATORE,TN,10.99,76.96,23.205.118.109 +BR,BLUMENAU,SC,-26.93,-49.05,187.59.4.154 +US,MCKEESPORT,PA,40.3339,-79.8011,23.192.161.21 +DE,FRANKEN,RP,50.50,7.23,80.157.170.221 +KZ,KUSTANAY,"",53.17,63.58,2.21.240.40 +US,ANDOVER,KS,37.7002,-97.0855,23.77.234.35 +US,TITUSVILLE,FL,28.5340,-80.8427,184.51.145.7 +US,NEWNAN,GA,33.3877,-84.8596,23.79.240.48 +UA,CHERKASY,"",49.43,32.07,23.14.94.228 +UZ,KASHKADARYA,"",38.97,65.78,23.76.205.111 +US,GOODLETTSVILLE,TN,36.3233,-86.7133,23.220.100.224 +RU,VORONEZH,"",51.67,39.17,213.155.156.208 +FR,VILLEURBANNE,"",45.77,4.88,2.16.117.190 +US,NEHALEM,OR,45.7222,-123.6842,192.80.13.117 +US,ALEXANDERCITY,AL,32.9346,-85.9597,23.79.240.48 +US,SANDPOINT,ID,48.4219,-116.5059,184.27.179.181 +AT,WINKL,"",48.38,15.90,195.145.147.101 +UA,NIKOLAEV,"",46.97,32.00,2.22.52.105 +US,SHENANDOAH,VA,38.4921,-78.5764,184.29.107.20 +US,MCLEMORESVILLE,TN,35.9867,-88.5772,69.31.132.226 +JP,YOKOSUKA,14,35.28,139.67,117.104.139.162 +US,CAPECORAL,FL,26.5778,-81.9505,23.79.240.48 +BD,TEJGAON,"",23.77,90.40,23.57.76.20 +ZW,HARARE,"",-17.86,31.03,165.165.46.36 +US,ARLINGTONHEIGHTS,IL,42.1121,-87.9793,107.14.38.218 +US,MOSESLAKE,WA,47.1758,-119.2892,206.104.149.146 +US,LONDONDERRY,NH,42.8794,-71.3877,184.25.109.200 +RU,LIPETSK,"",52.62,39.57,213.155.156.206 +US,EDWARDSVILLE,IL,38.8031,-89.9742,23.215.15.22 +US,BURNET,TX,30.8393,-98.2564,107.14.43.30 +JP,KUMAMOTO,43,32.80,130.72,117.104.139.136 +GG,SAINTPETERPORT,"",49.45,-2.53,81.25.206.208 +US,WHITEHOUSE,TX,32.2183,-95.2257,23.5.164.143 +TJ,DUSHANBE,"",38.57,68.77,2.21.240.40 +GB,WATFORD,EN,51.67,-0.40,23.67.255.158 +US,WHEATON,IL,41.8546,-88.116,23.67.60.222 +DE,TUBINGEN,BW,48.53,9.05,23.14.94.224 +NL,EINDHOVEN,"",51.45,5.47,92.122.189.114 +CD,GOMA,"",-5.32,14.40,95.101.34.105 +US,BOXBOROUGH,MA,42.4884,-71.5177,96.6.47.120 +RS,PETROVAC,"",42.42,20.43,23.62.237.137 +US,RANDOLPH,NJ,40.8481,-74.5726,184.51.125.79 +DE,WUNSIEDEL,BY,50.03,12.02,194.25.95.214 +AR,PUERTOMADRYN,"",-42.77,-65.05,72.246.216.139 +KR,INCHEON,"",37.45,126.73,61.111.58.229 +FR,NANTERRE,"",48.90,2.20,95.100.171.16 +IN,NASIK,MH,19.98,73.80,23.205.118.106 +GB,BARNSLEY,EN,53.55,-1.48,23.67.255.158 +US,ALIQUIPPA,PA,40.5921,-80.3191,184.28.17.76 +US,CONCORDIA,KS,39.4716,-97.7305,23.212.53.64 +RU,LESOSIBIRSK,"",58.29,92.39,213.155.156.207 +IN,NALGONDA,AP,17.05,79.27,23.205.118.106 +US,SHERIDAN,AR,34.3151,-92.3357,63.216.54.229 +US,EASLEY,SC,34.8763,-82.5796,23.79.240.48 +US,EAGLEPASS,TX,28.5841,-100.2545,23.74.2.7 +US,FORESTLAKE,MN,45.2627,-93.0169,107.14.38.218 +US,PONDERAY,ID,48.3056,-116.5325,184.27.179.165 +CZ,OLOMOUC,"",49.58,17.25,23.62.237.135 +IR,IMAM,"",36.70,48.81,184.27.45.150 +US,REXBURG,ID,43.7568,-111.6247,184.27.179.165 +US,WAUKESHA,WI,42.9721,-88.2283,107.14.38.218 +US,CHESTERLAND,OH,41.5320,-81.3349,107.14.38.218 +US,RICELAKE,WI,45.5296,-91.7231,23.74.8.24 +US,MEADVILLE,PA,41.6151,-80.1336,63.216.54.229 +US,BOCARATON,FL,26.3583,-80.0834,23.74.2.7 +US,OKEECHOBEE,FL,27.4513,-80.9004,184.27.45.157 +NL,BRUNSSUM,"",50.95,5.97,92.122.189.85 +GB,COLCHESTER,EN,51.88,0.90,88.221.87.112 +NL,SCHIPHOL,"",52.30,4.75,23.62.100.152 +BA,LUKA,"",43.95,18.48,194.25.95.219 +US,DELTONA,FL,28.9054,-81.2458,184.51.145.7 +US,ROCKHILL,SC,34.8891,-81.0214,184.51.35.215 +BR,SANTOS,SP,-23.95,-46.33,190.98.140.184 +BG,PLOVDIV,"",42.15,24.75,92.122.215.89 +US,ASHEBORO,NC,35.6532,-79.8468,209.18.41.27 +US,RATON,NM,36.7885,-104.4527,63.226.34.162 +US,VERSAILLES,KY,38.0184,-84.7389,63.216.54.216 +US,OPALOCKA,FL,25.9069,-80.2583,23.79.240.36 +AT,OBERPUCHENAU,"",48.32,14.23,195.145.147.109 +US,BILOXI,MS,30.4030,-88.8982,24.143.197.207 +US,ZANESVILLE,OH,39.9489,-82.0572,23.74.8.24 +US,ROY,UT,41.1733,-112.049,23.61.195.160 +DE,FLENSBURG,SH,54.78,9.43,194.25.95.214 +IR,BARAN,"",33.87,49.06,96.17.182.136 +US,PORTARTHUR,TX,29.7569,-94.1898,23.5.164.143 +US,OAKLEY,CA,37.9884,-121.6913,96.17.12.48 +CA,THORNHILL,ON,43.80,-79.42,72.246.43.237 +US,STONEMOUNTAIN,GA,33.7941,-84.2001,72.246.247.5 +US,SPRUCEPINE,NC,35.8996,-82.076,96.16.12.228 +US,PLEASANTVILLE,NY,41.1279,-73.7929,184.51.125.68 +US,SLATINGTON,PA,40.7371,-75.6374,23.67.242.156 +US,ENCINO,CA,34.1566,-118.5233,184.50.26.194 +US,STEELE,ND,46.8514,-99.9609,23.63.227.214 +US,WATERBURY,CT,41.5584,-73.0516,65.113.249.8 +US,CITRUSHEIGHTS,CA,38.6954,-121.2709,23.212.52.82 +RS,OBRENOVAC,"",43.04,22.72,2.20.45.104 +US,MOUNTGILEAD,OH,40.5633,-82.7592,65.113.249.11 +US,TEXASCITY,TX,29.3796,-94.9168,96.17.163.161 +US,GREENWELLSPRINGS,LA,30.5283,-91.0015,96.17.153.157 +US,AMELIA,OH,39.0167,-84.2069,165.254.207.111 +US,ANGOLA,IN,41.6594,-85.0055,23.67.60.220 +US,VALPARAISO,IN,41.4608,-87.0555,184.27.120.65 +JP,TOSHIMA,13,34.52,139.28,72.246.184.81 +US,MUSKEGON,MI,43.2355,-86.2532,23.67.60.223 +RU,NIJNIINOVGOROD,"",56.33,44.00,80.239.222.190 +KZ,TALDYK,"",54.65,67.80,23.14.94.214 +IT,NAPOLI,"",40.83,14.25,195.10.50.196 +US,COLLIERVILLE,TN,35.0596,-89.6789,23.79.240.48 +GB,BURY,EN,50.90,-0.57,195.245.125.107 +US,EASTTROY,WI,42.7945,-88.4154,107.14.38.227 +PL,GRZEGORZ,"",53.23,18.68,2.22.52.102 +UA,EUPATORIA,CRIMEA,45.20,33.36,92.122.215.89 +US,FARGO,ND,46.9259,-96.8507,165.254.114.164 +FR,PUGETVILLE,"",43.28,6.13,92.122.189.85 +SA,DHAHRAN,"",26.30,50.13,2.20.249.12 +KH,THMEY,"",11.80,104.93,23.76.205.90 +AU,DUBBO,NSW,-32.25,148.62,104.72.70.95 +CN,PUTIAN,FJ,25.44,119.01,184.50.87.178 +US,BLUESPRINGS,MO,39.0167,-94.2817,23.77.234.35 +US,PLAQUEMINE,LA,30.2546,-91.307,96.17.153.157 +DE,WITTEN,NW,51.43,7.33,194.25.95.212 +US,LOSALAMITOS,CA,33.7944,-118.0653,184.50.26.204 +ID,BATAM,"",1.08,104.03,23.0.162.40 +US,PENDLETON,OR,45.6098,-118.7308,184.27.179.159 +ID,CILEGON,"",-6.02,106.05,111.94.254.81 +CA,LEAMINGTON,ON,42.05,-82.58,72.246.43.215 +US,BARSTOW,CA,35.1476,-117.2068,184.50.26.204 +CA,WHITEHORSE,YT,60.72,-135.05,184.150.187.236 +US,HANNIBAL,MO,39.7145,-91.4209,204.93.47.216 +US,SOUTHBOSTON,VA,36.7012,-79.0269,184.29.107.38 +US,DESERTHOTSPRINGS,CA,33.9562,-116.5278,184.50.26.204 +PH,BAYAN,"",14.82,121.05,202.78.83.175 +FR,LECANNET,"",43.57,7.02,88.221.83.140 +US,EASTSTROUDSBURG,PA,41.0716,-75.148,184.26.44.42 +US,PORTAGE,WI,43.5939,-89.4754,23.74.8.8 +NI,MANAGUA,"",12.15,-86.27,184.26.44.38 +US,OPP,AL,31.2505,-86.2666,184.51.35.226 +US,KALISPELL,MT,48.0396,-113.5304,184.27.179.187 +US,FREEHOLD,NJ,40.2229,-74.3007,184.51.125.68 +US,SUWANEE,GA,34.0498,-84.0681,184.28.127.58 +IN,GOA,GA,15.50,73.92,23.211.135.66 +US,FERNANDINABEACH,FL,30.6056,-81.5268,23.79.240.36 +US,BELLEFONTE,PA,40.9455,-77.7398,23.192.161.21 +US,CALLAHAN,FL,30.5784,-81.8357,23.79.240.36 +RU,TVER,"",56.86,35.89,165.254.1.206 +US,ALGONQUIN,IL,42.1655,-88.2877,23.67.60.223 +TW,NANKANG,"",25.05,121.60,61.220.62.175 +US,LAQUINTA,CA,33.6713,-116.2873,184.50.26.201 +US,BARBERTON,OH,41.0203,-81.628,65.113.249.8 +US,WAYNESVILLE,NC,35.5777,-83.0002,23.79.240.48 +DE,PASSAU,BY,48.58,13.48,195.145.147.107 +VN,QUAN,"",18.43,105.75,23.76.205.111 +CH,LAUSANNE,"",46.53,6.67,193.247.167.211 +AR,ROQUESAENZPENA,"",-26.78,-60.45,200.123.201.219 +US,DONALDSONVILLE,LA,30.1206,-91.0306,23.215.15.32 +NZ,NEWPLYMOUTH,"",-39.07,174.08,219.88.186.165 +US,DEVILSLAKE,ND,48.1943,-98.7957,107.14.38.224 +IN,VASAI,MH,19.35,72.80,23.211.135.110 +RU,OREL,"",55.73,34.10,217.212.227.31 +US,LACRESCENTA,CA,34.2360,-118.2448,23.216.10.78 +US,COPPELL,TX,32.9610,-96.986,23.215.15.9 +US,ORLANDPARK,IL,41.6163,-87.8577,23.67.60.222 +US,PORTSAINTLUCIE,FL,27.2963,-80.2966,23.79.240.48 +UA,KRIVOYROG,"",47.92,33.35,23.14.94.224 +US,OPELIKA,AL,32.5952,-85.3164,23.79.240.36 +IS,REYKJAVIK,"",64.15,-21.95,23.212.108.8 +MX,TORREON,COA,25.55,-103.43,173.223.52.67 +ZA,POTCHEFSTROOM,"",-26.72,27.10,41.193.163.53 +AU,BROADMEADOWS,VIC,-37.67,144.90,184.84.221.85 +US,GRAMERCY,LA,30.1097,-90.6848,96.17.153.162 +US,PHILIPSBURG,PA,40.8621,-78.166,23.67.242.139 +US,BELCHERTOWN,MA,42.2771,-72.4022,23.67.244.224 +US,ORANGECITY,FL,28.9410,-81.3069,23.33.186.134 +US,LELAND,NC,34.2757,-78.1004,209.18.41.27 +KH,SIHANOUK,"",10.63,103.50,203.106.85.13 +GR,IRAKLIO,"",37.80,22.72,85.205.31.89 +US,JEFFERSON,GA,34.1004,-83.5698,63.216.54.231 +US,WALTERBORO,SC,32.8889,-80.7102,184.51.35.226 +DE,TETTNANG,BW,47.67,9.60,23.14.94.224 +IR,RAZAVI,"",34.28,58.47,165.254.96.242 +AR,CORDOBA,"",-31.40,-64.18,200.123.201.215 +CN,LANZHOU,GS,36.06,103.79,72.246.191.19 +US,POWDERSPRINGS,GA,33.8752,-84.6983,23.79.240.48 +US,BOURBONNAIS,IL,41.1818,-87.8739,23.67.60.222 +CI,ABIDJAN,"",5.32,-4.03,195.245.125.107 +US,WESTDESMOINES,IA,41.5662,-93.743,173.197.194.166 +US,CLARKSSUMMIT,PA,41.4656,-75.7341,184.25.157.155 +US,SAINTPETER,MN,44.3784,-94.0784,23.79.255.149 +US,NEWBREMEN,OH,40.4590,-84.3985,23.74.8.8 +US,FORTMORGAN,CO,40.1574,-103.8158,107.14.32.235 +CN,FOSHAN,GD,23.03,113.12,184.84.239.175 +AT,LOHNSBURG,"",48.15,13.40,84.53.146.39 +PL,GLIWICE,"",50.28,18.67,2.22.52.109 +HK,QUARRYBAY,"",22.28,114.22,23.76.205.90 +US,LUMBERTON,NC,34.6231,-78.9771,209.18.41.27 +FI,PORI,"",61.48,21.78,23.215.15.9 +US,BYRON,GA,32.6425,-83.775,23.212.53.64 +RU,KURSK,"",51.73,36.19,2.21.240.40 +MW,BLANTYRE,"",-15.78,35.00,217.89.107.166 +US,WESTWEGO,LA,29.9137,-90.2078,23.215.15.9 +AU,BENTLEY,WA,-32.00,115.92,23.62.224.33 +US,YAZOOCITY,MS,32.8273,-90.5829,23.215.15.32 +CD,KINSHASA,"",-4.33,15.31,77.67.40.172 +KZ,AKTOBE,"",43.98,78.80,80.239.149.123 +PL,ZYCHLIN,"",52.25,19.62,80.239.222.190 +US,FAIRBORN,OH,39.8173,-84.0025,107.14.38.218 +US,BLUEISLAND,IL,41.6641,-87.6855,107.14.38.218 +US,LISLE,IL,41.7894,-88.0823,23.67.60.223 +GB,LUTON,EN,51.88,-0.42,88.221.87.94 +US,NOLENSVILLE,TN,35.9350,-86.6688,165.254.138.175 +US,LACONIA,NH,43.5670,-71.4823,165.254.48.154 +US,SHOWLOW,AZ,34.0940,-110.0867,65.116.149.102 +US,GRIFFITH,IN,41.5177,-87.4208,107.14.38.218 +US,SCHENECTADY,NY,42.8148,-73.9393,72.247.10.237 +IR,GOLESTAN,"",35.77,51.46,80.239.149.123 +US,BEAUFORT,SC,32.4316,-80.67,165.254.138.165 +TR,BURSA,"",40.58,30.90,77.67.29.116 +JP,YOKKAICHI,24,34.97,136.62,117.104.139.162 +US,KEARNY,NJ,40.7563,-74.1217,184.26.44.40 +BR,CUIABA,MT,-15.58,-56.08,72.246.216.144 +US,ALPINE,CA,32.8087,-116.7197,184.50.26.204 +MA,RABAT,"",34.03,-6.83,95.100.171.27 +US,ROCKLAND,ME,44.1308,-69.1301,24.143.199.156 +US,HARRISBURG,PA,40.2628,-76.8813,23.67.242.139 +KZ,AKTAU,"",48.03,72.83,23.14.94.224 +US,SHREWSBURY,MA,42.2859,-71.7148,63.238.85.161 +US,PALMETTO,FL,27.5213,-82.5728,23.33.186.101 +US,LATHAM,NY,42.7511,-73.7732,107.14.38.217 +TR,ERCIYES,"",38.63,35.58,80.15.235.161 +US,EASTON,PA,40.7421,-75.2249,184.29.107.38 +SG,KALLANG,"",1.33,103.87,96.17.180.175 +US,OZARK,MO,36.9964,-93.1892,209.170.117.178 +US,MIDDLEBURY,VT,43.9961,-73.1846,184.29.107.20 +FR,ALGRANGE,"",49.35,6.05,88.221.15.110 +US,HOMOSASSA,FL,28.7478,-82.5258,23.34.56.147 +US,AGOURAHILLS,CA,34.1403,-118.7625,184.87.195.99 +CN,ZHUZHOU,HN,27.83,113.15,72.246.191.16 +PL,KALISZ,"",52.95,20.65,2.22.52.101 +US,DENHAMSPRINGS,LA,30.5870,-90.9124,23.212.53.64 +DE,KRUMMESSE,SH,53.78,10.65,92.122.207.164 +US,TARPONSPRINGS,FL,28.1455,-82.7568,184.27.45.157 +US,GILBERTSVILLE,PA,40.3096,-75.5833,184.26.44.38 +US,VALRICO,FL,27.9126,-82.237,23.33.186.101 +IN,MANDAPAM,TN,9.28,79.12,96.17.182.130 +PL,PILAWAGORNA,"",50.70,16.73,2.22.61.99 +US,SHAKOPEE,MN,44.7514,-93.5146,63.151.29.12 +IT,RIMINI,"",44.06,12.58,213.144.173.198 +US,WAYNESBURG,PA,39.8611,-80.1706,63.216.54.229 +US,GRANBURY,TX,32.4158,-97.782,204.93.47.216 +US,WALTHILL,NE,42.1478,-96.478,23.79.255.149 +IT,PIEMONTE,"",42.78,12.55,2.18.240.95 +US,NORTHFORTMYERS,FL,26.7437,-81.9862,23.79.240.36 +SE,HELSINGBORG,M,56.05,12.70,23.65.29.106 +US,BOONE,NC,36.2085,-81.6605,23.79.240.36 +US,LOSBANOS,CA,36.9711,-120.9668,23.212.52.93 +DZ,TIZIOUZOU,"",36.72,4.05,90.84.53.194 +CA,BRANTFORD,ON,43.13,-80.27,72.246.43.215 +US,NEWRIVER,AZ,33.8763,-112.0502,184.50.26.194 +FR,MONTESSON,"",48.92,2.15,2.16.117.190 +ID,RAYA,"",1.08,118.53,23.0.162.54 +US,LOCUSTGROVE,GA,33.3564,-84.1119,72.246.247.5 +US,WESTNEWYORK,NJ,40.7879,-74.0112,184.26.44.38 +US,NORTHOLMSTED,OH,41.4153,-81.9188,23.67.242.139 +US,CUDAHY,WI,42.9465,-87.8638,107.14.38.217 +US,POSTFALLS,ID,47.7405,-116.9576,184.26.93.116 +US,INVERNESS,FL,28.8296,-82.2553,23.33.186.101 +US,SKIATOOK,OK,36.3833,-96.0366,165.254.138.175 +PL,ZAMBROW,"",52.98,22.25,2.22.52.109 +IR,LIR,"",34.70,49.75,2.22.52.105 +US,CLOQUET,MN,46.7232,-92.5588,65.113.249.11 +US,MOCKSVILLE,NC,35.9339,-80.5455,209.18.41.23 +US,PEKIN,IL,40.5452,-89.6011,184.27.120.65 +AU,CAIRNS,QLD,-16.92,145.77,23.209.183.61 +HU,KECSKEMET,"",46.90,19.78,72.247.10.241 +DK,EM,"",57.35,9.92,2.21.240.61 +RO,BRASOV,"",45.63,25.58,2.22.52.102 +US,GRANDVIEW,WA,46.2604,-119.9241,67.131.104.14 +US,HIGHPOINT,NC,35.9808,-80.1272,184.27.45.150 +US,HAMPSTEAD,NC,34.4359,-77.683,23.79.240.37 +CO,BELLO,"",6.33,-75.55,23.215.15.22 +IR,PARS,"",35.74,51.53,23.62.238.220 +US,SENATOBIA,MS,34.6336,-89.8203,96.17.153.162 +RO,ORADEA,"",47.07,21.93,81.196.26.198 +SE,GOTEBORG,O,57.72,11.97,213.155.156.208 +US,WINDHAM,ME,43.7950,-70.4037,165.254.35.197 +US,WEYMOUTH,MA,42.2076,-70.9575,184.25.109.196 +US,MASCOUTAH,IL,38.4590,-89.7628,204.93.47.220 +US,SANCLEMENTE,CA,33.4046,-117.5066,23.212.53.64 +US,RISON,AR,33.9470,-92.1633,23.74.8.24 +US,OSHKOSH,WI,43.9500,-88.5387,184.50.26.179 +HU,SZEGED,"",46.25,20.17,23.14.94.214 +TR,HATAY,"",36.23,36.12,193.45.15.198 +IN,MALIANDMUNJERI,MH,18.53,73.87,117.239.189.99 +JP,UTSUNOMIYA,09,36.55,139.87,96.7.251.95 +US,SEGUIN,TX,29.5278,-97.9363,96.17.163.161 +FR,ROUVIGNIES,"",50.33,3.43,2.16.117.190 +GP,POINTEAPITRE,"",16.23,-61.52,184.26.44.38 +US,FORTEUSTIS,VA,37.1626,-76.5808,23.220.148.122 +US,GOSHEN,NY,41.3906,-74.3406,24.143.199.188 +US,LAURENS,SC,34.4899,-82.0542,23.79.240.48 +US,SUMTER,SC,33.9242,-80.1986,209.18.41.23 +US,GLENDIVE,MT,47.0499,-104.5596,184.51.35.215 +US,VICKSBURG,MI,42.1149,-85.4789,23.67.60.223 +US,MIDVALE,UT,40.6150,-111.8913,184.84.180.68 +FR,OUISTREHAM,"",49.28,-0.25,2.16.117.190 +US,ENUMCLAW,WA,47.1782,-121.6415,184.27.179.159 +US,NORTHANSON,ME,44.9516,-69.9465,165.254.35.182 +UA,MAKEEVKA,"",48.03,37.97,2.21.240.61 +US,CORSICANA,TX,32.0635,-96.4417,184.27.179.181 +JP,NIHO,35,34.22,131.55,117.104.139.162 +US,DILLON,MT,45.1146,-112.8794,107.14.32.235 +US,FORTDODGE,IA,42.5075,-94.2531,63.151.29.15 +US,BADAXE,MI,43.7988,-82.998,65.113.249.8 +US,KILLINGWORTH,CT,41.3791,-72.5783,184.25.109.200 +FR,CORBEIL,"",48.60,2.48,2.16.117.200 +US,WESTORANGE,NJ,40.7895,-74.2629,184.26.44.38 +US,ZEPHYRHILLS,FL,28.2333,-82.1815,23.34.56.142 +PL,WYRZYSK,"",53.17,17.28,2.22.52.102 +IN,KAKINADA,AP,16.93,82.22,23.205.118.109 +CZ,LITOMYSL,"",49.87,16.32,23.62.237.135 +JP,TOKAI,23,35.03,136.89,23.3.104.15 +US,ROLLA,MO,37.9394,-91.763,63.216.54.236 +CA,SHERBROOKE,QC,45.40,-71.90,204.93.33.141 +TH,SONGKHLA,"",7.20,100.60,61.19.12.177 +US,DODGECITY,KS,37.6960,-100.1054,23.215.15.9 +BA,SARAJEVO,"",43.85,18.38,23.14.94.224 +US,WAGONER,OK,35.9683,-95.3871,23.5.164.146 +US,TUCUMCARI,NM,35.0485,-103.7548,64.129.104.132 +US,THURMONT,MD,39.5936,-77.4215,23.192.161.16 +AU,WARRAGUL,VIC,-38.17,145.93,210.11.142.65 +US,ITASCA,IL,41.9751,-88.0186,23.67.60.220 +US,FORTCAMPBELL,KY,36.6606,-87.4578,23.212.53.64 +CH,BASEL,"",47.57,7.60,195.145.147.109 +US,HALLANDALE,FL,25.9808,-80.1486,23.79.240.36 +US,EASTAURORA,NY,42.7704,-78.5853,209.18.41.27 +US,ROYERSFORD,PA,40.2034,-75.5319,23.67.242.156 +US,SHALLOTTE,NC,33.9593,-78.431,184.51.35.215 +US,OAKHARBOR,WA,48.3182,-122.6341,23.212.59.64 +IE,PORTLAOISE,"",53.03,-7.30,88.221.222.34 +US,JERSEYVILLE,IL,39.1259,-90.3475,96.17.14.16 +US,LITITZ,PA,40.1769,-76.295,184.25.157.155 +US,BUTTE,MT,45.9274,-112.5042,165.254.1.165 +RO,ONESTI,"",46.25,26.75,81.196.26.236 +US,MONCKSCORNER,SC,33.1483,-80.0528,184.51.35.226 +SE,FALKENBERG,N,56.90,12.50,2.21.240.61 +US,BELLMAWR,NJ,39.8669,-75.093,23.67.60.220 +US,HOUGHTON,MI,47.1004,-88.5759,184.85.215.165 +KH,BOEUNG,"",12.43,105.12,23.15.10.106 +US,REEDSBURG,WI,43.5282,-90.0016,184.85.215.165 +HK,KOWLOONTONG,"",22.33,114.18,23.76.205.111 +US,TILTON,NH,43.4812,-71.5745,184.25.109.196 +US,ROBERTSDALE,AL,30.6097,-87.6111,184.51.35.215 +US,JACKSONHEIGHTS,NY,40.7514,-73.8836,209.18.41.27 +US,SNELLVILLE,GA,33.7958,-83.9918,23.79.240.36 +US,FORTLUPTON,CO,40.0874,-104.8664,23.212.53.75 +CA,MONCTON,NB,46.08,-64.77,209.148.192.57 +US,CLARKSTON,WA,46.2148,-117.2463,165.254.144.32 +US,LITTLEFALLS,NJ,40.8835,-74.2057,184.26.44.40 +PL,KUTNO,"",52.23,19.37,2.22.52.101 +US,WEBSTER,MN,44.5239,-93.3702,23.67.60.220 +ZW,ZIMBABWE,"",-20.27,30.92,41.193.163.53 +DE,HERNE,NW,51.55,7.22,23.14.94.220 +PL,RZESZOW,"",50.05,22.00,77.67.96.116 +TH,PATHUMTHANI,"",14.02,100.53,61.19.12.79 +US,ELSA,TX,26.2988,-97.9827,204.2.223.91 +CH,WIL,"",47.60,8.50,92.122.215.67 +US,FERNLEY,NV,39.5869,-119.1525,23.61.195.149 +US,VANDALIA,OH,39.8973,-84.2232,107.14.38.218 +US,HURON,SD,44.3587,-98.2248,107.14.38.224 +US,HORNLAKE,MS,34.9498,-90.0305,184.84.180.98 +US,OAKHURST,CA,37.5934,-119.4077,173.223.52.67 +US,MILAN,TN,35.9258,-88.7624,204.2.243.132 +IR,SISTAN,"",36.95,49.75,23.14.94.224 +JP,AOMORI,02,40.82,140.75,72.246.191.16 +US,LAYTON,UT,41.1018,-111.9067,184.84.180.101 +BG,BANSKO,"",41.83,23.48,2.20.142.173 +FR,AX,"",42.72,1.83,23.200.87.58 +US,ALLIANCE,OH,40.9181,-81.1273,96.6.47.120 +US,HUGO,OK,34.0348,-95.5268,96.16.7.101 +PL,KOZIENICE,"",51.58,21.57,2.22.52.102 +US,FORESTPARK,GA,33.6133,-84.3728,23.212.53.64 +US,KILLEN,AL,34.9168,-87.5035,23.220.100.224 +BZ,BELIZECITY,"",17.48,-88.18,23.74.2.7 +KR,POHANG,"",36.03,129.37,125.56.214.147 +US,SOUTHMILWAUKEE,WI,42.9118,-87.8624,107.14.38.227 +US,WINTERSPRINGS,FL,28.6860,-81.2771,23.34.56.147 +US,MEXICO,MO,39.1882,-91.8924,204.93.47.220 +US,BOZEMAN,MT,45.6891,-110.9295,107.14.32.228 +KZ,URALSK,"",51.23,51.37,2.20.142.173 +US,WESTHAVEN,CT,41.2716,-72.9666,184.25.109.213 +BE,OVERHEID,"",51.07,4.27,23.62.100.152 +US,GLENALLEN,VA,37.6656,-77.5069,184.26.44.38 +US,BROCKPORT,NY,43.2485,-77.9306,107.14.38.217 +US,MAQUOKETA,IA,42.1200,-90.7234,165.254.207.117 +US,MARTINSFERRY,OH,40.1258,-80.7518,23.192.161.21 +US,ROLLINGMEADOWS,IL,42.0703,-88.0209,107.14.38.218 +US,CYNTHIANA,KY,38.4145,-84.2859,23.79.240.48 +US,DANVERS,MA,42.5739,-70.9505,184.25.109.200 +US,ZILLAH,WA,46.4400,-120.2284,184.27.179.181 +RS,BEOGRAD,"",44.82,20.47,2.20.45.104 +US,SANTAFESPRINGS,CA,33.9363,-118.0653,184.50.26.194 +FR,ANNECY,"",45.90,6.12,92.122.189.85 +US,HEBERCITY,UT,40.2386,-111.1499,23.61.195.149 +US,LENOIR,NC,35.9137,-81.5393,23.79.240.48 +JP,FUKUSHIMA,07,37.75,140.47,72.246.184.92 +US,MOORESVILLE,NC,35.5822,-80.8122,209.18.41.27 +US,LAPORTE,TX,29.6785,-95.0483,96.17.163.165 +MX,QUERETARO,QUE,20.60,-100.38,187.141.2.151 +US,MURRYSVILLE,PA,40.4616,-79.6658,23.192.161.16 +US,NEWBRUNSWICK,NJ,40.4861,-74.4473,184.26.44.42 +US,HADDONHEIGHTS,NJ,39.8789,-75.0646,23.67.242.139 +US,FAIRBANKS,AK,64.5037,-147.6591,23.212.59.64 +NZ,PAPAKURA,"",-37.08,174.95,219.88.186.167 +UA,KHERSON,"",46.63,32.60,217.212.227.25 +AU,RANDWICK,NSW,-33.92,151.24,23.62.8.21 +US,SOUTHBEND,IN,41.6699,-86.2535,23.63.227.227 +US,MERIDIANVILLE,AL,34.8710,-86.5547,23.220.100.223 +US,BREAUXBRIDGE,LA,30.2731,-91.9325,23.215.15.9 +GB,GATESHEAD,EN,54.95,-1.62,88.221.87.112 +US,STEVENSONRANCH,CA,34.3795,-118.5754,63.233.112.196 +IT,POGGIBONSI,"",43.47,11.15,77.67.29.116 +CA,CORNERBROOK,NF,48.95,-57.93,209.148.192.57 +DE,GREIFSWALD,MV,54.10,13.38,80.157.150.201 +US,PARAMOUNT,CA,33.8963,-118.1642,184.50.26.194 +US,GOOCHLAND,VA,37.7179,-78.0059,184.26.44.38 +US,BEACH,ND,47.0809,-103.8785,63.216.54.231 +US,LEWISCENTER,OH,40.1839,-82.9843,107.14.38.224 +CA,OLIVER,BC,49.18,-119.55,184.27.179.187 +US,SONORA,TX,30.4983,-100.5382,23.215.15.9 +ID,BINTANG,"",-7.25,107.20,23.0.162.21 +US,SLOCOMB,AL,31.0914,-85.5835,184.27.45.157 +GI,GIBRALTAR,"",36.13,-5.35,92.123.73.233 +BA,BIHAC,"",44.82,15.87,23.14.94.224 +JP,HIMEJI,28,34.82,134.70,23.3.74.113 +US,GREER,SC,34.8978,-82.2584,72.246.247.5 +US,LEWISTOWN,PA,40.6073,-77.5812,23.192.161.30 +US,LINCOLNTON,NC,35.4951,-81.2237,23.79.240.48 +US,MISHAWAKA,IN,41.6161,-86.1361,23.67.60.220 +US,ISLEOFPALMS,SC,32.8046,-79.7534,23.79.240.36 +FR,TAVERNY,"",49.03,2.22,2.16.117.200 +RU,ROSSIYA,"",54.82,32.42,92.122.189.114 +FR,SAINTEGENEVIEVEDESBOIS,"",48.63,2.33,2.20.243.42 +US,YELM,WA,46.8659,-122.5344,23.212.59.63 +US,ALLSTON,MA,42.3585,-71.13,184.29.107.38 +US,CRYSTALCITY,MO,38.2311,-90.378,204.93.47.220 +US,LAKESIDEMARBLEHEAD,OH,41.5249,-82.7767,23.74.8.24 +US,MENTOR,OH,41.6763,-81.3297,107.14.38.218 +US,RICHLANDCENTER,WI,43.4015,-90.4109,184.85.215.165 +US,SOUTHAVEN,MS,34.9597,-89.9817,23.212.53.64 +US,WALTHAM,MA,42.3876,-71.2411,184.28.17.76 +IR,SEPAHAN,"",35.67,51.17,184.25.157.155 +US,TEMPLE,TX,31.0795,-97.3287,107.14.43.29 +US,DINUBA,CA,36.5216,-119.3869,23.212.52.79 +US,SAINTALBANS,VT,44.8111,-73.0813,23.192.161.30 +PL,TORUN,"",53.03,18.60,80.239.149.123 +US,NORTHWILKESBORO,NC,36.1585,-81.1478,23.79.240.36 +ID,PAKANBARU,"",0.53,101.45,118.98.37.99 +US,LEVELLAND,TX,33.6122,-102.3901,107.14.36.199 +SE,ESKILSTUNA,D,59.37,16.50,2.21.240.61 +ZA,PAROW,"",-33.90,18.60,165.165.46.36 +US,MCALESTER,OK,34.9351,-95.8929,174.76.226.117 +US,MOULTRIE,GA,31.1855,-83.7469,63.216.54.229 +FR,NEUILLYPLAISANCE,"",48.87,2.52,2.16.117.190 +AU,WENTWORTH,NSW,-34.12,141.92,210.11.142.64 +US,CLAYTON,NC,35.6321,-78.4269,209.18.41.23 +US,MILLEDGEVILLE,GA,33.0769,-83.3032,63.216.54.231 +US,BRYANSROAD,MD,38.6499,-77.0865,23.192.161.16 +IR,ALBORZ,"",34.73,50.97,23.14.94.224 +RO,ZALAU,"",47.20,23.05,80.239.222.190 +US,KANNAPOLIS,NC,35.5043,-80.6706,209.18.41.27 +HK,NORTHPOINT,"",22.30,114.20,184.84.239.186 +US,NOTREDAME,IN,41.7197,-86.2504,107.14.32.235 +PY,FERNANDODELAMORA,"",-25.32,-57.60,200.91.22.117 +US,BRUSH,CO,40.1479,-103.5597,173.197.194.159 +CN,SUQIAN,JS,33.95,118.30,23.15.10.91 +US,CHITTENANGO,NY,43.0618,-75.8688,107.14.38.217 +ZA,POINT,"",-29.87,31.05,41.193.163.45 +US,WESTFARGO,ND,46.8625,-96.9269,107.14.38.218 +TR,ANKARA,"",39.94,32.86,2.20.142.166 +GA,LIBREVILLE,"",0.38,9.45,195.245.125.249 +IN,AGRA,UP,27.18,78.02,213.248.108.233 +US,SUNPRAIRIE,WI,43.2012,-89.2037,184.85.215.170 +DE,CLAUSTHALZELLERFELD,NI,51.80,10.33,195.95.193.132 +US,GUALALA,CA,38.8361,-123.4304,23.63.227.214 +PL,BIALYSTOK,"",53.13,23.15,80.157.149.129 +IN,KARUR,TN,10.95,78.08,96.17.182.136 +US,TRUTHORCONSEQUENCES,NM,33.1866,-106.8454,23.212.53.64 +US,CLEMSON,SC,34.6740,-82.8212,64.86.201.118 +DE,LAUCHHAMMER,BB,51.50,13.80,195.95.193.150 +US,DAVISON,MI,43.0361,-83.513,23.63.227.227 +JP,SENDAI,04,38.26,140.89,117.104.139.136 +US,MINDEN,NE,40.5009,-98.902,23.212.53.64 +US,OCONOMOWOC,WI,43.1140,-88.4931,107.14.38.217 +US,RUSKIN,FL,27.7115,-82.4202,23.33.186.134 +US,QUEENSVILLAGE,NY,40.7303,-73.748,184.26.44.42 +US,BELPRE,OH,39.3164,-81.6086,107.14.38.227 +US,HARKERHEIGHTS,TX,31.0283,-97.6473,107.14.43.29 +US,LINTON,IN,39.0608,-87.1852,23.67.60.220 +SE,BOLLNAS,X,61.35,16.37,2.21.240.40 +US,WALLEDLAKE,MI,42.5503,-83.474,23.67.60.222 +US,CHIPPEWAFALLS,WI,44.9743,-91.4379,65.113.249.8 +DK,SKANDERBORG,"",56.03,9.93,23.65.29.93 +DE,FRIEDRICHSHAFEN,BW,47.65,9.48,23.14.94.224 +JP,HAKODATE,01,41.75,140.72,23.3.104.15 +US,GIRARD,OH,41.1741,-80.6779,107.14.38.217 +TR,ADANA,"",38.63,28.88,193.45.15.199 +MZ,MAPUTO,"",-25.97,32.59,165.165.46.38 +US,INVERGROVEHEIGHTS,MN,44.8348,-93.0357,23.67.60.220 +US,PINEVILLE,KY,36.7417,-83.6911,173.197.192.214 +US,BRAZIL,IN,39.5158,-87.1262,23.63.227.214 +GB,OVER,EN,52.32,0.02,195.245.125.249 +ID,RIAU,"",-1.72,105.93,23.0.162.40 +CN,SHANGXI,ZJ,29.30,119.90,23.76.205.111 +US,BALDWINCITY,KS,38.8017,-95.2855,23.67.60.223 +US,PROSPER,TX,33.2340,-96.7848,184.28.23.4 +US,NORMAL,IL,40.5373,-88.9869,23.67.60.222 +US,GILLETTE,WY,44.4735,-105.5945,23.212.53.75 +US,POTEAU,OK,35.0533,-94.5362,23.215.15.32 +US,FRIENDSWOOD,TX,29.5125,-95.188,96.17.163.161 +US,HOLDENVILLE,OK,35.0789,-96.319,96.16.7.101 +US,NEWPORTRICHEY,FL,28.2352,-82.7347,23.34.56.142 +NL,BREDA,"",51.57,4.80,92.122.189.114 +TR,KADIKOY,"",40.82,32.83,80.15.235.163 +KZ,KOKCHETAV,"",53.28,69.39,213.155.156.207 +US,METHUEN,MA,42.7346,-71.189,23.67.244.240 +NG,LIKE,"",6.90,7.48,95.101.2.122 +CZ,FRYDEKMISTEK,"",49.68,18.33,23.62.237.133 +PL,PODGORNE,"",53.42,21.78,61.111.58.229 +US,PIQUA,OH,40.1702,-84.2793,107.14.38.218 +IR,ILAM,"",33.64,46.43,80.239.149.123 +UA,SIMFEROPOL,CRIMEA,44.95,34.10,2.22.52.101 +US,VANBUREN,AR,35.4580,-94.2992,174.76.226.117 +IR,ARDABIL,"",38.25,48.30,23.62.238.215 +US,BANGOR,ME,44.8521,-68.8311,107.14.38.224 +FR,VELIZY,"",48.80,2.18,23.200.87.59 +US,BELTSVILLE,MD,39.0347,-76.9076,184.28.17.55 +JP,ASHIKAGA,09,36.33,139.45,23.3.104.20 +US,LOSALAMOS,NM,35.8375,-106.349,23.212.52.88 +CA,ALLISTON,ON,44.15,-79.87,72.246.43.215 +US,FOLSOM,CA,38.6648,-121.1414,96.17.12.48 +US,SCOTTSBORO,AL,34.7061,-86.0958,184.51.35.215 +US,DURANT,OK,34.0185,-96.3864,184.28.23.4 +MX,PATZCUARO,MIC,19.52,-101.60,23.212.53.64 +IN,ULUBARI,AS,26.50,90.42,23.57.76.18 +GB,STEVENAGE,EN,51.92,-0.22,23.67.255.158 +US,BETHESDA,MD,38.9806,-77.1008,23.192.161.16 +ID,BANTEN,"",-6.05,106.15,23.0.162.21 +RU,KOPEYSK,"",55.12,61.62,2.21.240.61 +US,PAINESVILLE,OH,41.6851,-81.2077,96.17.9.8 +US,PICKENS,SC,34.9245,-82.7166,72.246.247.5 +US,SANCARLOS,CA,37.4970,-122.2756,23.212.52.79 +US,CHARLESTOWN,WV,39.2635,-77.8778,23.192.161.21 +RU,NALCHIK,"",43.50,43.62,2.21.240.61 +US,BLAKELY,GA,31.3824,-84.9419,63.216.54.236 +US,STRONGSVILLE,OH,41.3148,-81.8093,96.17.9.14 +US,WESTHENRIETTA,NY,43.0409,-77.6888,107.14.38.227 +US,GENESEE,MI,43.1100,-83.6218,65.113.249.8 +PL,NOWYTOMYSL,"",52.32,16.15,2.22.61.99 +US,STATENISLAND,NY,40.6308,-74.0923,24.143.199.188 +US,BEEBE,AR,35.1238,-91.9422,96.17.14.15 +MO,TAIPA,"",22.15,113.55,202.175.5.87 +ID,BEKASI,"",-6.23,106.98,202.43.190.239 +US,HOPKINSVILLE,KY,36.8832,-87.4597,23.220.100.224 +US,OVERTON,NV,36.5809,-114.605,64.145.95.145 +RO,PITESTI,"",44.85,24.87,81.196.26.236 +US,WISCONSINRAPIDS,WI,44.3431,-89.7334,65.113.249.8 +US,DANAPOINT,CA,33.4774,-117.7048,64.86.201.118 +US,ELKHART,IN,41.7235,-85.9764,23.74.8.8 +US,BIGSPRING,TX,32.2854,-101.4495,23.5.164.143 +CA,SAINTLAMBERT,QC,45.48,-73.50,67.69.197.160 +US,MATTESON,IL,41.5063,-87.7446,107.14.38.218 +US,HANOVER,NH,43.7256,-72.2368,184.25.109.200 +CA,HULL,QC,45.43,-75.73,67.69.197.160 +AU,WERRIBEE,VIC,-37.90,144.67,184.84.221.87 +US,DELRAYBEACH,FL,26.4576,-80.0806,23.79.240.37 +US,MCCOMB,MS,31.1693,-90.3678,165.254.138.175 +US,MACHESNEYPARK,IL,42.3589,-89.0409,107.14.38.217 +VN,DANANG,"",21.72,105.35,112.175.42.120 +US,EUREKA,IL,40.7102,-89.2521,23.74.8.24 +US,HARMONY,PA,40.8638,-80.1313,209.48.37.188 +US,COUNCILBLUFFS,IA,41.2146,-95.8574,23.79.255.153 +AR,FUNES,"",-32.92,-60.82,200.123.201.215 +US,BUDA,TX,30.0694,-97.8797,184.26.93.116 +MN,BAYANGOL,"",48.91,106.09,80.239.237.230 +US,FORESTCITY,NC,35.2700,-81.8676,23.79.240.36 +AT,ALKOVEN,"",48.28,14.10,195.145.147.109 +IT,GENOVA,"",44.42,8.95,193.45.15.198 +US,KITTANNING,PA,40.8196,-79.4288,184.26.44.40 +UA,KHMELNITSKIY,"",49.42,27.00,2.21.240.61 +KZ,SEMEY,"",50.41,80.23,80.239.222.169 +US,GARRETSON,SD,43.7606,-96.5516,23.63.227.223 +US,DUNKIRK,NY,42.4788,-79.3113,107.14.38.227 +ID,MATARAM,"",-7.17,106.67,23.0.162.54 +US,UTICA,MI,42.6730,-82.9952,23.67.60.223 +US,VERNAL,UT,40.1055,-109.4989,63.235.21.141 +US,KELLOGG,ID,47.7187,-116.0875,24.143.194.180 +IN,VISHAKHAPATNAM,AP,17.70,83.30,23.57.69.157 +DE,ISERLOHN,NW,51.37,7.70,92.122.207.179 +US,ALTUS,OK,34.6829,-99.3441,23.215.15.22 +US,BOLIVAR,MO,37.6066,-93.4143,63.216.54.236 +US,BERWYN,IL,41.8314,-87.7884,107.14.38.227 +US,WESTCOLUMBIA,SC,33.9973,-81.0998,64.129.104.132 +US,ELLENSBURG,WA,47.0155,-120.3114,184.27.179.159 +US,LOMITA,CA,33.7935,-118.3174,184.50.26.204 +US,OPELOUSAS,LA,30.5146,-92.101,23.79.240.36 +US,SICKLERVILLE,NJ,39.7334,-74.9786,23.67.242.139 +US,CRAWFORDSVILLE,IN,40.0313,-86.9257,65.113.249.11 +US,MURPHY,NC,35.1195,-84.1344,184.27.45.150 +RU,DAGOMYS,"",43.66,39.65,92.122.189.114 +MX,XALAPAENRIQUEZ,VER,19.53,-96.92,165.254.1.206 +US,LIBERTYLAKE,WA,47.6567,-117.0803,184.27.179.187 +US,EDGEWATER,FL,28.9786,-80.9236,184.51.145.22 +ID,SURAKARTA,"",-6.42,105.87,23.0.162.46 +US,NEWMILFORD,NJ,40.9338,-74.0194,23.67.242.139 +US,OXONHILL,MD,38.8052,-76.9958,23.192.161.16 +US,MORRISVILLE,PA,40.1994,-74.8145,184.27.45.150 +BG,DOBRICH,"",42.02,25.52,92.122.189.85 +US,BLUFFTON,SC,32.2534,-80.8971,165.254.138.165 +DE,SCHLEGEL,TH,50.40,11.62,46.33.70.97 +US,LACANADAFLINTRIDGE,CA,34.2241,-118.1106,23.216.10.54 +CA,LONGUEUIL,QC,45.53,-73.52,72.246.43.215 +US,LEESSUMMIT,MO,38.9333,-94.3253,23.77.234.11 +RU,KALININA,"",53.52,36.03,2.21.240.61 +US,CLAWSON,MI,42.5361,-83.1514,23.67.60.222 +US,WHEATRIDGE,CO,39.7756,-105.108,184.84.180.98 +US,SCOTTDALE,PA,40.1122,-79.5869,65.121.209.127 +NL,DRONTEN,"",52.53,5.72,92.122.189.114 +DE,BEIERFELD,SN,50.57,12.80,92.122.215.67 +AU,TUGGERAH,NSW,-33.32,151.42,104.72.70.95 +DE,STROM,HB,53.08,8.72,194.25.95.225 +US,MOUNTAIRY,NC,36.4840,-80.6333,209.18.41.27 +CN,PO,AH,33.88,115.77,184.50.87.178 +IR,ARA,"",36.20,53.72,217.212.227.31 +AT,PURKERSDORF,"",48.20,16.17,195.145.147.107 +DE,STUHR,NI,53.03,8.75,80.157.170.221 +BA,TESANJ,"",44.61,17.99,46.33.70.216 +IN,AJMER,RJ,26.45,74.63,117.239.189.115 +PL,TOMASZOW,"",52.33,21.02,80.239.149.123 +DE,DOTTERNHAUSEN,BW,48.23,8.80,194.25.95.225 +MY,PENANG,"",5.42,100.33,203.106.85.113 +US,KANKAKEE,IL,41.1223,-87.9467,23.67.60.217 +PS,RAMALLAH,"",31.90,35.20,92.122.189.85 +ID,KETAPANG,"",-6.15,106.80,23.0.162.21 +IN,SECUNDERABAD,AP,17.45,78.50,23.205.118.109 +US,ASTON,PA,39.8645,-75.4349,184.26.44.42 +MY,KOTABHARU,"",4.40,101.08,58.27.124.241 +US,SAINTMICHAEL,MN,45.1957,-93.7002,63.151.29.12 +US,TIFTON,GA,31.4504,-83.5086,72.246.247.30 +US,PHENIXCITY,AL,32.3790,-85.1147,72.246.247.5 +UA,LUGANSK,"",47.37,37.10,80.239.237.231 +US,MALVERN,AR,34.3189,-92.8629,96.16.7.120 +NO,SANDEFJORD,"",59.13,10.23,2.21.240.40 +US,UPPERMARLBORO,MD,38.7800,-76.7676,184.28.17.76 +FR,STIRINGWENDEL,"",49.20,6.93,80.157.150.201 +US,ASHTABULA,OH,41.8515,-80.79,107.14.38.218 +US,MARLTON,NJ,39.8786,-74.8969,184.26.44.42 +DE,LUDWIGSHAFEN,RP,49.48,8.44,2.20.142.173 +DE,BADRA,TH,51.40,10.97,23.14.94.214 +IN,SHIMLA,RJ,28.68,74.57,96.17.182.136 +IR,KHORASAN,"",35.70,47.27,184.25.157.155 +US,GROVELAND,MA,42.7505,-71.0153,184.25.109.213 +US,GRANITEFALLS,NC,35.8300,-81.4147,23.79.240.37 +US,SMITHVILLE,TN,35.9094,-85.7998,23.79.240.36 +US,HOLT,MI,42.6321,-84.5423,23.67.60.222 +US,OCEANA,WV,37.7347,-81.5521,96.6.47.120 +US,NEWBURGH,IN,37.9445,-87.4053,23.63.227.214 +US,FOLKSTON,GA,30.9136,-82.1547,63.216.54.216 +US,ELMER,NJ,39.5646,-75.1874,184.27.45.150 +FR,LEBLANCMESNIL,"",48.93,2.45,2.16.117.190 +RU,CHEBOKSARY,"",56.13,47.25,213.155.156.212 +HK,HOMANTIN,"",22.32,114.18,203.186.47.99 +US,TAUNTON,MA,41.9112,-71.1289,184.25.109.196 +US,BIGBEARCITY,CA,34.2842,-116.9019,23.216.10.78 +LS,MASERU,"",-29.32,27.48,184.27.179.181 +US,ANGIER,NC,35.4757,-78.7203,23.79.240.36 +IN,SHILIGURI,WB,26.72,88.42,96.17.182.130 +UA,SEVASTOPOL,CRIMEA,44.60,33.53,88.221.15.111 +US,BATESVILLE,MS,34.3450,-89.8815,96.17.153.157 +IN,ANANTAPUR,AP,14.68,77.60,23.205.118.109 +US,NEWBRAUNFELS,TX,29.6944,-98.0725,96.17.163.165 +US,KILGORE,TX,32.3769,-94.8692,131.103.137.122 +US,COATESVILLE,PA,39.9700,-75.8325,184.26.44.42 +BD,DIAL,"",24.93,89.08,23.75.23.140 +US,MENTONE,CA,34.1048,-117.051,184.50.26.192 +TH,CHAENG,"",15.55,102.38,92.122.189.85 +NL,HILVERSUM,"",52.23,5.18,95.101.2.112 +US,INGRAM,TX,30.1349,-99.4936,23.215.15.32 +US,PIERRE,SD,44.3693,-100.0402,107.14.38.218 +LT,KALVARIJA,"",54.73,25.28,2.21.240.40 +US,COOKEVILLE,TN,36.1802,-85.4582,23.79.240.37 +US,NORTHMANCHESTER,IN,40.9831,-85.7915,23.74.8.8 +BI,BUJUMBURA,"",-3.38,29.36,23.205.169.195 +FI,SALO,"",60.73,24.18,2.21.240.61 +NZ,HOWICK,"",-36.89,174.92,219.88.186.172 +DE,HERTEN,NW,51.60,7.13,194.25.95.212 +US,LAFOLLETTE,TN,36.3953,-84.1409,23.79.240.37 +IT,BARI,"",41.13,16.85,193.45.15.198 +IR,GHARBI,"",28.94,53.24,23.14.94.228 +KR,SUWON,"",37.28,127.02,184.51.199.132 +US,SOUTHPORT,NC,34.0734,-78.0547,209.18.41.23 +DJ,DJIBOUTI,"",11.60,43.15,95.101.34.109 +US,MANDEVILLE,LA,30.3898,-90.0068,184.28.127.55 +IN,THANE,MH,19.20,72.97,96.17.180.166 +US,CORNELIUS,NC,35.4867,-80.8605,72.246.247.30 +US,LINDENHURST,NY,40.6894,-73.3745,184.26.44.38 +DK,LYNGBY,"",55.77,12.52,23.65.29.106 +US,GRASSVALLEY,CA,39.2183,-120.9247,23.61.195.165 +US,FREDONIA,WI,43.4948,-87.9836,107.14.38.217 +LT,KLAIPEDA,"",55.72,21.12,77.67.27.235 +US,MOUNTAINHOME,ID,43.2609,-115.7811,206.104.149.146 +JP,URAWA,11,35.87,139.65,23.3.104.16 +US,RUSSELL,KS,38.8001,-98.8561,23.215.15.32 +US,SENECA,SC,34.7097,-82.9753,72.246.247.30 +US,WALLER,TX,30.0958,-95.9497,96.17.163.161 +JP,KANAGAWA,07,37.58,139.92,202.229.2.227 +US,BERNE,IN,40.6587,-84.8982,65.113.249.11 +SD,KHARTOUM,"",15.59,32.53,23.212.108.28 +US,FORTPIERCE,FL,27.4538,-80.5447,23.79.240.36 +RO,TARGUMURES,"",46.55,24.57,81.196.26.231 +DE,DILLENBURG,HE,50.73,8.28,95.100.169.105 +FR,EVRY,"",48.63,2.45,2.16.117.200 +GB,WIGAN,EN,53.53,-2.62,184.27.139.24 +DE,WORMS,RP,49.64,8.36,92.122.215.67 +US,BUNA,TX,30.4154,-93.9904,165.254.207.117 +US,NEDERLAND,TX,29.9798,-94.0164,107.14.36.199 +US,KERMAN,CA,36.7225,-120.1318,23.61.195.165 +US,LEVITTOWN,PA,40.1722,-74.822,23.67.242.156 +US,SLIDELL,LA,30.2612,-89.7907,184.28.127.58 +US,WELLSBURG,WV,40.2340,-80.5842,184.27.45.157 +US,WESTON,FL,26.0970,-80.3968,72.246.65.23 +US,DEQUINCY,LA,30.3794,-93.4077,23.5.164.146 +PL,STALOWAWOLA,"",50.57,22.05,80.15.235.156 +TR,ANTALYA,"",36.88,30.70,80.239.222.169 +US,STURGIS,MI,41.8205,-85.4431,23.63.227.214 +JP,OKIDATE,02,40.83,140.73,72.246.184.84 +US,GALLOWAY,OH,39.9347,-83.1992,96.17.9.14 +IL,REHOVOT,"",31.90,34.82,82.102.137.137 +US,ARNOLD,MO,38.4305,-90.3985,96.17.14.15 +US,COLVILLE,WA,48.6776,-117.7361,206.104.149.146 +CZ,MILICIN,"",49.57,14.67,92.122.215.89 +US,KRUM,TX,33.2811,-97.313,23.5.164.146 +US,BREA,CA,33.9296,-117.8713,23.61.195.163 +BG,HASKOVO,"",41.93,25.55,93.186.137.228 +FR,DREUX,"",48.73,1.37,2.16.117.200 +JP,TOYONAKA,27,34.78,135.47,23.3.104.20 +US,HERMITAGE,TN,36.1840,-86.6033,23.212.53.75 +US,SELLERSBURG,IN,38.3931,-85.7713,107.14.38.218 +AR,MENDOZA,"",-32.88,-68.82,190.98.167.230 +CN,XINGFA,ZJ,28.44,120.46,72.246.191.16 +US,SHERMAN,TX,33.6449,-96.5899,23.215.15.9 +ID,KALIMANTAN,"",1.62,109.18,96.17.180.177 +US,ADAIRSVILLE,GA,34.3646,-84.9223,72.246.247.5 +RE,REUNION,"",-21.07,55.27,2.20.243.42 +CN,LANGFANG,HE,39.52,116.70,184.84.239.186 +US,BURLEY,ID,42.5011,-113.8145,67.131.104.14 +US,OAKLAWN,IL,41.7129,-87.7521,23.67.60.223 +US,MARTINSBURG,WV,39.4645,-77.9544,184.27.45.150 +PL,TYLAWA,"",49.47,21.70,77.67.96.116 +US,CAMPHILL,PA,40.2398,-76.9205,23.192.161.16 +US,DEERFIELD,MA,42.5381,-72.6067,184.25.109.201 +GB,PRESTON,EN,51.57,-0.30,184.27.139.24 +MY,MELAKA,"",2.20,102.25,58.27.124.248 +US,KLAMATHFALLS,OR,42.2527,-121.8343,184.27.179.159 +US,STEAMBOATSPRINGS,CO,40.4850,-106.8312,184.84.180.101 +US,NEENAH,WI,44.1857,-88.529,107.14.38.218 +US,FLOWERYBRANCH,GA,34.1717,-83.8975,72.246.247.5 +US,ESSEX,MD,39.2951,-76.4387,23.192.161.16 +TH,BANGRAK,"",13.73,100.53,80.239.222.167 +US,LORIS,SC,34.0573,-78.931,184.51.35.215 +JP,JOETSU,15,37.10,138.25,210.175.5.177 +US,VOORHEES,NJ,39.8445,-74.9532,23.67.60.220 +MX,NAVOJOA,SON,27.10,-109.43,173.223.52.70 +GB,KINGSTONUPONHULL,EN,53.72,-0.33,173.222.211.203 +US,PIGEONFORGE,TN,35.7901,-83.5658,23.79.240.48 +AT,RIEDIMINNKREIS,"",48.22,13.50,77.67.27.235 +RO,BOTOSANI,"",47.75,26.67,81.196.26.236 +US,CLEVES,OH,39.2102,-84.7493,165.254.207.117 +US,MANHATTAN,KS,39.1124,-96.5124,23.215.15.9 +US,MINOT,ND,48.1414,-101.3873,107.14.38.218 +US,EASTHARTFORD,CT,41.7810,-72.6206,184.27.45.150 +US,NEWSMYRNABEACH,FL,28.9806,-81.0592,23.34.56.147 +US,MARINGOUIN,LA,30.4461,-91.569,204.93.43.168 +PL,KACZOR,"",50.58,23.15,2.22.52.102 +VN,TANG,"",22.62,104.17,92.122.189.85 +US,GRANDHAVEN,MI,43.0131,-86.1392,23.63.227.227 +FR,AIXENPROVENCE,"",43.53,5.43,2.16.117.200 +US,MONTGOMERYVILLAGE,MD,39.1743,-77.1915,23.192.161.30 +CZ,ZBRASLAV,"",49.97,14.40,92.122.215.67 +US,MANVEL,TX,29.4777,-95.3591,184.28.23.24 +PL,CIS,"",51.28,20.22,2.22.52.105 +US,CLIFTONFORGE,VA,37.8336,-79.7447,184.27.45.157 +US,HASTINGS,MN,44.6820,-92.8732,63.151.29.15 +US,MANTENO,IL,41.2496,-87.8949,184.27.120.65 +MY,JOHORBAHRU,"",1.47,103.75,96.17.180.166 +CA,SUDBURY,ON,46.50,-80.97,67.69.197.92 +TR,ATAKOY,"",38.73,30.55,193.45.15.198 +IR,ZANJAN,"",36.66,48.49,96.17.182.136 +CA,SAINTCATHARINES,ON,43.17,-79.23,72.246.43.215 +US,SHELBY,NC,35.3693,-81.5992,184.27.45.150 +IN,MATHURA,UP,27.50,77.68,124.124.252.160 +US,THEDALLES,OR,45.5517,-121.219,184.27.179.187 +US,RIOGRANDE,NJ,39.0203,-74.8749,184.26.44.38 +SN,MEDINA,"",14.68,-17.45,81.52.201.98 +US,VIRDEN,IL,39.5001,-89.8147,65.113.249.11 +TR,IZMIT,"",40.77,29.92,193.45.15.198 +GR,PATRA,"",38.25,21.73,80.157.169.4 +US,BOGALUSA,LA,30.7419,-89.8828,96.17.153.162 +PL,GOLENIOW,"",53.57,14.82,2.22.52.101 +DE,HAND,NW,50.80,6.05,2.20.142.166 +SB,HONIARA,"",-9.43,159.95,173.197.192.214 +US,ADA,OK,34.7965,-96.7902,23.215.15.22 +CZ,KOLIN,"",50.02,15.20,23.62.237.133 +US,DOWNSVILLE,WI,44.7748,-91.9318,23.74.8.24 +US,ROSEBURG,OR,43.2103,-123.4286,206.104.149.146 +TH,PHUKET,"",7.88,98.40,184.84.180.68 +RO,RAMNICUSARAT,"",45.38,27.05,23.62.237.135 +AT,KLOSTERNEUBURG,"",48.30,16.32,46.33.70.104 +US,OAKCREEK,WI,42.8802,-87.9005,107.14.38.224 +CZ,USTINADLABEM,"",50.67,14.03,23.62.237.135 +JP,WAKAYAMA,30,34.09,135.09,65.116.149.102 +UA,MAKSIM,"",51.20,30.95,92.122.215.67 +FR,BAGNOLET,"",48.87,2.42,2.16.117.190 +US,CHISHOLM,MN,47.5741,-92.8546,23.215.15.32 +US,COTTONDALE,AL,33.1618,-87.3671,192.204.82.239 +US,WILKESBARRE,PA,41.2438,-75.8848,184.25.157.169 +US,FLANDERS,NJ,40.8455,-74.7097,184.26.44.38 +CA,PORTPERRY,ON,44.10,-78.93,72.246.43.215 +RU,VYATKA,"",58.47,35.67,80.239.237.80 +NO,SKI,"",59.72,10.83,2.21.240.40 +IL,JERUSALEM,"",31.77,35.23,96.17.163.165 +MY,LABUAN,"",5.28,115.24,23.15.10.91 +US,HONESDALE,PA,41.6240,-75.2495,184.26.44.38 +US,MAPLESHADE,NJ,39.9516,-74.9946,184.26.44.38 +HK,STANLEY,"",22.22,114.20,96.16.12.216 +US,MAUMELLE,AR,34.8504,-92.3916,96.16.7.101 +DE,NEUBIBERG,BY,48.08,11.68,195.95.193.134 +US,PERTHAMBOY,NJ,40.5225,-74.2746,184.26.44.38 +US,TYRONE,PA,40.6572,-78.2228,184.26.44.38 +US,LILBURN,GA,33.8704,-84.1214,72.246.247.5 +US,KEASBEY,NJ,40.5142,-74.3145,184.26.44.38 +CZ,OPAVA,"",49.95,17.92,23.62.237.137 +MX,VERACRUZ,VER,19.20,-96.13,165.254.1.206 +US,GOOSECREEK,SC,32.9946,-79.999,23.79.240.44 +MY,KOTAKINABALU,"",5.98,116.07,96.17.180.155 +US,WALNUTRIDGE,AR,36.1072,-90.9128,96.16.7.120 +US,SHAMOKIN,PA,40.7842,-76.5797,184.26.44.42 +RO,PETROSANI,"",43.72,25.63,88.221.93.157 +US,OSSEO,MN,45.0992,-93.4917,23.67.60.220 +US,CLEMMONS,NC,36.0036,-80.372,209.18.41.23 +BD,SYLHET,"",24.53,91.87,96.17.180.166 +US,SELAH,WA,46.8035,-120.6744,23.212.59.85 +FR,VILLEPINTE,"",48.97,2.53,217.212.239.109 +US,GADSDEN,AL,34.0512,-85.9648,23.212.53.75 +US,RAILROAD,PA,39.7607,-76.6988,23.192.161.16 +CN,LUOYANG,HA,34.68,112.45,184.50.87.178 +US,LUTZ,FL,28.1415,-82.4686,23.34.56.147 +US,HARRINGTON,DE,38.9242,-75.6177,23.192.161.21 +CN,HUIZHOU,GD,23.08,114.40,184.50.87.178 +VU,LOLTONG,"",-15.55,168.13,88.221.15.111 +US,PORTORCHARD,WA,47.5378,-122.5894,165.254.1.165 +US,HAMDEN,CT,41.3720,-72.9418,184.25.109.213 +US,MENOMONIE,WI,44.8570,-92.0071,184.85.215.165 +US,LAKEINTHEHILLS,IL,42.1832,-88.3453,107.14.38.227 +US,GREENSBURG,IN,39.3206,-85.4768,23.67.60.217 +US,DACULA,GA,33.9712,-83.8738,72.246.247.30 +US,WHITETHORN,CA,40.0707,-124.0094,63.151.119.16 +CN,LANTIAN,GD,23.87,114.22,107.14.44.212 +US,NORWOOD,MA,42.1844,-71.1953,184.25.109.213 +US,MERRITTISLAND,FL,28.2972,-80.6751,23.33.186.134 +US,SUMMERSVILLE,WV,38.3477,-80.8565,184.27.45.150 +US,BROOKINGS,SD,44.3014,-96.8692,23.63.227.227 +CA,CHICOUTIMI,QC,48.43,-71.07,67.69.197.106 +US,DARDANELLE,AR,35.1648,-93.2292,23.79.240.37 +AR,ALVEAR,"",-33.07,-60.62,190.98.167.220 +US,LOMALINDA,CA,34.0484,-117.2603,184.50.26.179 +US,REDOAK,TX,32.5150,-96.8153,96.16.7.120 +US,TOOELE,UT,40.5393,-112.3531,23.215.15.9 +IL,YAKUM,"",32.25,34.85,212.143.162.162 +US,HOCKLEY,TX,30.0437,-95.8249,96.17.163.165 +TR,KONYA,"",37.87,32.52,88.221.93.157 +DE,SOLTAU,NI,52.98,9.83,92.122.207.179 +US,TURTLECREEK,PA,40.4160,-79.8228,72.247.10.237 +US,MASONCITY,IA,43.1451,-93.1385,23.63.227.214 +ID,MENTENG,"",-6.22,106.83,23.0.162.21 +AR,SANMARTIN,"",-34.57,-58.55,23.61.195.149 +US,PORTNECHES,TX,29.9818,-93.9497,184.26.93.116 +US,ERIE,CO,40.0782,-105.0312,184.84.180.98 +US,SWANSBORO,NC,34.7017,-77.1399,209.18.41.23 +RU,BAZA,"",60.60,40.15,2.21.240.40 +US,BLAIRSVILLE,PA,40.4741,-79.2341,23.192.161.16 +SK,KOSICE,"",48.72,21.25,23.62.237.138 +US,BUCYRUS,OH,40.8150,-82.9723,107.14.38.217 +US,WHEELING,IL,42.1311,-87.9211,107.14.38.227 +PR,CAGUAS,"",18.2357,-66.0369,72.246.65.38 +KR,SILLIMDONG,"",37.23,128.08,112.175.42.120 +ES,LINARES,"",40.58,-5.92,92.122.188.163 +US,SKOKIE,IL,42.0355,-87.7304,107.14.38.218 +US,MOUNTCLEMENS,MI,42.5974,-82.8814,69.22.154.219 +US,BEULAVILLE,NC,34.9398,-77.7738,63.151.29.12 +US,RAINBOWCITY,AL,33.9427,-86.0638,23.79.240.36 +FR,BOUGIVAL,"",48.87,2.13,2.16.117.190 +US,HONDO,TX,29.4252,-99.1005,96.17.163.161 +TR,ACI,"",39.73,34.18,80.239.237.231 +US,WESTHAVERSTRAW,NY,41.2083,-73.9777,184.26.44.42 +ID,SOLO,"",-7.58,110.83,23.0.162.21 +GB,WINNERSH,EN,51.42,-0.87,88.221.87.94 +US,SAINTJOHNSBURY,VT,44.4161,-71.9767,63.141.200.241 +IN,AURANGABAD,MH,19.88,75.33,117.239.189.115 +RU,URENGOY,"",65.97,78.37,2.21.240.61 +DE,GELSENKIRCHEN,NW,51.52,7.05,2.20.142.173 +US,EMMETT,ID,43.9488,-116.5537,192.80.13.117 +US,SIDNEY,OH,40.2838,-84.1519,107.14.38.218 +US,CADILLAC,MI,44.2433,-85.5328,23.63.227.214 +US,HOLLIS,NY,40.7171,-73.7686,24.143.199.188 +US,ALVARADO,TX,32.4269,-97.2192,23.5.164.143 +ID,RUNGKUT,"",-7.33,112.77,23.0.162.54 +US,MOKENA,IL,41.5339,-87.885,23.67.60.220 +US,DONORA,PA,40.1785,-79.8649,23.192.161.16 +FR,LORIENT,"",47.75,-3.37,2.16.117.200 +US,WHEATLAND,WY,42.0178,-105.0984,23.212.53.75 +RU,SURGUT,"",53.93,51.23,2.21.240.61 +AT,AMSTETTEN,"",48.12,14.87,23.14.94.224 +RU,VSI,"",60.05,32.38,80.239.237.93 +US,JORDAN,MN,44.6530,-93.5873,23.67.60.222 +US,GRANGER,IN,41.7389,-86.1232,23.67.60.220 +UA,SUDAK,CRIMEA,44.85,34.97,92.122.189.85 +US,LINCOLNSHIRE,IL,42.1941,-87.9317,23.67.60.217 +US,RIVERHEAD,NY,40.9530,-72.642,184.26.44.40 +TR,CANAKKALE,"",40.15,26.40,80.239.237.230 +US,CRAWFORDVILLE,FL,30.1758,-84.3754,184.84.180.98 +FM,POHNPEI,"",8.0001,147.0001,96.17.70.93 +US,TEAGUE,TX,31.6463,-96.2786,184.28.23.24 +US,CANONSBURG,PA,40.2740,-80.1538,184.27.45.162 +US,SOLON,OH,41.3834,-81.4439,107.14.38.224 +US,FREDERICKSBURG,VA,38.2993,-77.4869,96.6.47.120 +US,FOXLAKE,IL,42.3951,-88.1755,23.67.60.222 +IR,ESFAHAN,"",32.66,51.67,96.17.182.136 +US,WHITEWATER,WI,42.8048,-88.7446,184.85.215.170 +US,HARRISONVILLE,MO,38.6236,-94.3109,205.185.195.170 +AT,SCHWAZ,"",47.33,11.70,46.33.70.97 +DK,RY,"",56.08,9.77,95.101.2.122 +US,STAUNTON,VA,38.1221,-79.0825,184.26.44.42 +US,HUGHSON,CA,37.5927,-120.8607,23.216.10.54 +IN,MOHALI,PB,30.78,76.69,23.211.135.66 +US,CALHOUN,GA,34.4962,-84.9097,72.246.247.5 +US,CHILDRESS,TX,34.4383,-100.1979,23.5.164.146 +US,BELOIT,WI,42.5474,-89.1358,184.85.215.165 +US,PORTTOWNSEND,WA,48.0260,-122.8596,24.244.17.205 +KZ,BALKHASH,"",46.67,79.33,217.212.227.25 +CA,SAINTETHERESE,QC,45.63,-73.85,67.69.197.95 +US,FINDLAY,OH,41.0444,-83.65,209.18.41.27 +US,IMPERIAL,MO,38.3874,-90.4319,96.17.14.16 +FR,CACHAN,"",48.78,2.33,2.16.117.190 +US,MORAGA,CA,37.8315,-122.1123,23.61.195.163 +US,NEWBERLIN,WI,42.9726,-88.1602,23.63.227.214 +IN,JHANSI,UP,25.43,78.58,96.17.182.136 +US,DEERFIELDBEACH,FL,26.3109,-80.1005,23.79.240.36 +US,GOLDEN,CO,39.7164,-105.2437,63.235.21.141 +US,WESTMONROE,LA,32.5473,-92.2007,184.84.180.92 +US,TIFFIN,OH,41.1540,-83.2212,184.27.45.150 +CZ,BENESOV,"",49.78,14.68,23.62.237.135 +IN,TIRUCHENGODU,TN,11.38,77.93,117.239.240.76 +CA,WELLAND,ON,42.98,-79.25,72.246.43.237 +US,GREENBELT,MD,39.0047,-76.8758,23.192.161.21 +IR,SHIRAZ,"",29.61,52.54,96.17.182.136 +SG,WOODLANDS,"",1.44,103.78,23.5.165.168 +AU,MOUNTWAVERLEY,VIC,-37.88,145.13,184.84.238.30 +GB,SHEFFIELD,EN,53.37,-1.50,173.222.211.190 +US,INDIALANTIC,FL,28.1099,-80.5786,23.33.186.134 +US,MORRISPLAINS,NJ,40.8475,-74.4826,184.26.44.42 +US,TILLAMOOK,OR,45.4813,-123.6742,184.27.179.165 +US,LUDINGTON,MI,43.9737,-86.4001,23.63.227.227 +US,NORTHBROOK,IL,42.1255,-87.8406,165.254.207.111 +AU,CEDUNA,SA,-32.12,133.67,23.205.117.4 +IT,PISA,"",43.72,10.38,2.18.240.95 +CN,QUZHOU,ZJ,28.97,118.87,72.246.191.19 +US,PERHAM,MN,46.6280,-95.6018,198.63.196.223 +US,BRADY,TX,31.0630,-99.3372,23.215.15.9 +US,BENSALEM,PA,40.1068,-74.9379,184.27.45.157 +US,MONTOURSVILLE,PA,41.2816,-76.8857,23.67.242.139 +US,HODGENVILLE,KY,37.5720,-85.7077,23.79.240.36 +US,BRYSONCITY,NC,35.5051,-83.603,96.6.47.106 +FI,RAAHE,"",64.68,24.48,46.33.64.237 +US,SAINTAUGUSTINE,FL,29.8475,-81.2787,80.239.237.231 +AF,ENAW,"",37.02,70.13,23.212.108.28 +US,GRAYSON,GA,33.8909,-83.9601,72.246.247.5 +CN,DEQING,ZJ,30.55,120.08,117.103.188.218 +BR,AMERICANA,SP,-22.74,-47.33,201.6.5.13 +US,CARTERSVILLE,GA,34.1498,-84.8279,23.79.240.36 +CN,XIANGTAN,HN,27.85,112.90,184.50.87.178 +JP,TOTTORI,31,35.50,134.23,117.104.139.162 +US,BELLEVIEW,FL,29.0589,-82.0588,23.34.56.142 +DE,ETTLINGEN,BW,48.95,8.40,92.122.207.164 +US,CREEDMOOR,NC,36.1139,-78.6265,184.27.45.150 +MQ,FORTDEFRANCE,"",14.60,-61.08,23.74.2.7 +CZ,TRINEC,"",49.68,18.65,23.62.237.137 +CN,HAIDIAN,BJ,39.98,116.30,184.51.199.145 +US,PAGOSASPRINGS,CO,37.1765,-106.8964,23.212.53.64 +US,STANTON,IA,40.9868,-95.099,65.113.249.8 +US,WAUNAKEE,WI,43.1852,-89.4585,23.63.227.214 +US,DUNDALK,MD,39.2639,-76.497,23.67.242.139 +US,SOUTHINGTON,CT,41.6129,-72.8728,184.28.17.76 +US,EUCLID,OH,41.5709,-81.5266,96.17.9.14 +US,LAKEOSWEGO,OR,45.4082,-122.6837,23.212.59.63 +US,MONTICELLO,IN,40.8005,-86.6926,23.67.60.217 +US,MORROBAY,CA,35.4012,-120.7993,23.216.10.78 +NZ,GREYMOUTH,"",-42.47,171.20,219.88.186.167 +HN,LACEIBA,"",13.80,-87.28,23.74.2.7 +US,PARKHILLS,MO,37.8386,-90.5648,204.93.47.220 +ZA,MIDRAND,"",-25.96,28.14,41.193.163.53 +US,PERU,IL,41.3434,-89.1366,184.27.120.65 +IN,TIRUVANNAMALAI,TN,12.22,79.07,184.25.157.155 +US,ARAB,AL,34.3320,-86.4894,204.2.243.135 +FI,VAASA,"",63.10,21.60,2.21.240.40 +CA,NORTHBATTLEFORD,SK,52.77,-108.28,184.150.187.237 +US,ROSEMOUNT,MN,44.7330,-93.0593,184.85.215.170 +AU,DONCASTER,VIC,-37.78,145.13,60.254.143.219 +NO,HORTEN,"",59.41,10.47,2.21.240.40 +IN,VADODARA,GJ,22.30,73.20,23.57.69.159 +RU,PODOLSK,"",55.43,37.55,2.21.240.61 +US,CANANDAIGUA,NY,42.8488,-77.3077,209.18.41.23 +US,HUTTO,TX,30.5231,-97.5348,63.141.200.241 +US,ROBESONIA,PA,40.3646,-76.1416,184.27.45.157 +US,MANKATO,MN,44.1156,-93.9984,184.85.215.165 +CN,SUZHOU,JS,31.31,120.62,72.246.191.16 +US,ALTAMONTESPRINGS,FL,28.6657,-81.3692,23.34.56.147 +US,LAVEEN,AZ,33.3032,-112.1882,63.226.34.165 +AU,CHELTENHAM,VIC,-37.97,145.05,184.84.238.9 +US,YOUNGSVILLE,LA,30.0840,-92.0053,23.215.15.9 +DE,KAMPLINTFORT,NW,51.50,6.53,92.122.189.85 +US,SANGER,TX,33.3623,-97.2076,23.5.164.146 +US,POST,TX,33.1799,-101.2984,205.185.195.170 +WS,APIA,"",-13.83,-171.73,63.217.8.137 +GB,STOURBRIDGE,EN,52.47,-2.13,195.245.125.107 +JP,MIYAGI,01,43.37,143.80,202.229.2.212 +US,SULPHUR,OK,34.4826,-96.973,107.14.43.30 +BD,MOLLA,"",23.80,90.92,96.17.180.166 +US,PONTEVEDRABEACH,FL,30.2396,-81.3855,184.51.145.7 +AT,HOCHSTRASS,"",48.13,15.97,195.145.147.108 +US,SUNNYSIDE,NY,40.7442,-73.9205,24.143.199.156 +US,CARLJUNCTION,MO,37.2082,-94.5634,209.170.117.178 +JP,FUSSA,13,35.74,139.33,23.15.1.67 +US,WESLACO,TX,26.1701,-97.9943,184.26.93.116 +US,IONIA,MI,43.0186,-85.0515,23.63.227.227 +US,CLIFTONPARK,NY,42.8536,-73.7851,107.14.38.218 +US,FARIBAULT,MN,44.3009,-93.28,23.79.255.153 +GB,WALFORD,EN,51.88,-2.60,23.67.255.106 +US,MERRILL,WI,45.2167,-89.8732,92.122.189.114 +US,MILTON,FL,30.7972,-86.9425,96.17.153.162 +US,MATAWAN,NJ,40.4118,-74.2499,23.67.242.139 +MY,KAMPAR,"",4.30,101.15,203.106.85.113 +CZ,SKUTEC,"",49.85,16.00,23.62.237.135 +DE,HATTINGEN,NW,51.40,7.17,195.145.147.101 +US,VILLARICA,GA,33.7153,-84.9212,23.79.240.37 +US,KENNER,LA,29.9910,-90.2553,96.17.153.157 +US,WESTBURY,NY,40.7560,-73.5739,184.26.44.38 +US,PHARR,TX,26.1569,-98.1914,184.26.93.116 +US,SAINTCLAIRSVILLE,OH,40.0964,-80.9221,23.192.161.21 +KZ,AKMOLA,"",42.67,70.97,80.239.237.80 +AT,TULLN,"",48.33,16.05,46.33.70.97 +CH,BUCHS,"",47.45,8.43,2.16.217.206 +US,FAIRLESSHILLS,PA,40.1749,-74.8541,23.79.240.37 +VC,KINGSTOWN,"",13.13,-61.22,23.74.2.12 +IT,LIMANA,"",46.09,12.14,2.18.240.114 +US,BAKER,LA,30.5884,-91.1684,23.215.15.32 +US,ARCHBALD,PA,41.5069,-75.5327,184.27.45.157 +US,CAMERON,MO,39.6971,-94.2694,209.170.117.178 +PW,PALAU,"",7.5002,134.5003,23.76.205.111 +NZ,TASMAN,"",-41.20,173.05,203.96.118.166 +US,MAYFIELD,KY,36.7237,-88.6867,69.31.132.233 +US,WILLIAMSTOWN,NJ,39.6478,-74.9514,184.26.44.38 +JP,SHOWA,05,39.87,140.08,72.246.191.19 +US,GROVECITY,PA,41.1722,-80.0759,65.121.209.141 +US,BETHELPARK,PA,40.3204,-80.0367,96.6.47.106 +US,MENDENHALL,MS,31.9629,-89.7927,96.17.153.157 +US,GARRETT,IN,41.3275,-85.1414,23.74.8.24 +US,LANDRUM,SC,35.1429,-82.1944,63.216.54.236 +ES,MAQUINAS,"",37.70,-4.12,80.239.237.231 +US,PLANTCITY,FL,27.9421,-82.1345,165.254.205.7 +BR,SAOJOSEDOSCAMPOS,SP,-23.18,-45.88,200.174.107.42 +US,BALACYNWYD,PA,40.0138,-75.23,184.27.45.157 +US,FLOWERMOUND,TX,33.0308,-97.0985,23.215.15.32 +US,OLMSTEDFALLS,OH,41.3740,-81.9211,96.17.9.14 +ID,MOJOKERTO,"",-7.47,112.43,23.0.162.54 +US,HAMMONTON,NJ,39.6370,-74.7602,23.67.60.217 +US,HERMOSABEACH,CA,33.8651,-118.3964,184.50.26.185 +US,VALDEZ,AK,60.9721,-146.4265,184.27.179.159 +AU,MASCOT,NSW,-33.93,151.20,23.62.8.21 +CZ,VITKOVICE,"",50.12,13.30,23.62.237.137 +AU,SOUTHBRISBANE,QLD,-27.48,153.02,23.62.8.25 +US,LOVESPARK,IL,42.3453,-89.0028,23.67.60.220 +RU,SOVETSK,"",53.94,37.63,2.20.142.166 +US,AVONLAKE,OH,41.4945,-82.016,107.14.32.235 +US,LYNDHURST,NJ,40.7971,-74.1109,23.67.60.222 +VI,CHRISTIANSTED,"",17.7488,-64.7039,23.34.56.142 +RO,SUCEAVA,"",47.63,26.25,81.196.26.198 +ID,BALIKPAPAN,"",-1.28,116.83,23.0.162.21 +US,CHRISTIANSBURG,VA,37.1299,-80.4092,96.6.47.120 +IR,AHVAZ,"",31.33,48.69,96.17.182.130 +US,ZACHARY,LA,30.6604,-91.1897,23.215.15.22 +MX,DURANGO,DUR,24.03,-104.67,173.223.52.67 +US,SAVOY,IL,40.0399,-88.2643,69.22.154.219 +AT,LEOBEN,"",47.38,15.10,23.62.237.133 +JP,NAKASHIMA,07,37.08,140.95,184.51.199.132 +US,WAUSEON,OH,41.5765,-84.1519,65.113.249.11 +US,HAMEL,MN,45.0776,-93.5754,23.67.60.220 +TR,VAN,"",38.50,43.38,88.221.93.150 +US,RINGGOLD,GA,34.8973,-85.1353,23.79.240.36 +DE,BIEDENKOPF,HE,50.92,8.53,23.14.94.228 +US,MULLINS,SC,34.1893,-79.2589,209.18.41.27 +AU,GOLDCOAST,QLD,-28.00,153.43,23.209.183.50 +FR,BESANCON,"",47.25,6.03,2.16.117.190 +US,MILLHALL,PA,41.0898,-77.4915,23.192.161.30 +IN,MAMALLAPURAM,TN,12.63,80.17,117.239.240.96 +US,KOKOMO,IN,40.5251,-86.1768,23.74.8.24 +FR,SAINTANDRELESVERGERS,"",48.28,4.05,2.16.117.190 +IT,NOLA,"",40.92,14.55,195.22.200.221 +DE,GARCHING,BY,48.13,12.60,23.14.94.220 +US,GREATBEND,KS,38.3903,-98.8296,23.215.15.9 +US,WESTPOINT,MS,33.6681,-88.7618,23.79.240.36 +US,CHESTER,VA,37.3415,-77.403,184.27.45.150 +DE,HAMM,NW,51.68,7.80,92.122.215.89 +US,LAMBERTVILLE,MI,41.7532,-83.627,23.63.227.214 +NO,ASKER,"",59.83,10.43,213.155.156.206 +US,CHECOTAH,OK,35.4498,-95.4869,174.76.226.117 +CZ,PRELOUC,"",50.03,15.57,23.62.237.135 +NL,ENSCHEDE,"",52.22,6.90,95.101.2.112 +US,MENDOCINO,CA,39.3125,-123.7473,23.61.195.165 +US,EQUALITY,IL,37.6964,-88.3404,205.185.195.170 +FR,MOUANSSARTOUX,"",43.62,6.97,81.52.201.98 +CA,SAINTJOHN,NB,45.27,-66.07,72.246.43.215 +US,NORTHCHARLESTON,SC,32.8537,-79.9839,184.27.45.150 +US,NORTHDARTMOUTH,MA,41.6650,-71.0141,184.29.107.38 +US,ELIZABETHCITY,NC,36.3018,-76.2238,63.151.29.15 +JP,HAKATA,27,34.48,135.43,23.3.74.113 +US,DALEVILLE,VA,37.4044,-79.9221,184.26.44.38 +TR,BUYUKCEKMECE,"",41.03,28.58,77.67.29.116 +JP,KAGAWA,35,34.07,131.03,117.104.139.162 +KR,ULSAN,"",35.54,129.32,125.56.214.169 +US,VESTAL,NY,42.0463,-76.0314,107.14.38.227 +DK,VEJLE,"",55.27,10.32,95.101.2.112 +US,TRIANGLE,VA,38.5576,-77.3506,184.27.45.157 +HK,SHEUNGWAN,"",22.28,114.15,58.27.124.248 +US,LEECHBURG,PA,40.6690,-79.6041,23.192.161.16 +CA,THOMPSON,MB,55.75,-97.87,23.74.8.8 +US,GRAHAM,WA,47.0168,-122.2798,23.212.59.63 +AU,NUNAWADING,VIC,-37.82,145.17,150.101.152.245 +US,DOVERPLAINS,NY,41.7225,-73.5844,184.26.44.38 +HK,TAIPO,"",22.45,114.17,23.76.205.90 +CO,BUCARAMANGA,"",4.98,-74.55,200.14.44.108 +US,BRICK,NJ,40.0399,-74.1255,23.67.242.156 +US,LONOKE,AR,34.7557,-91.9476,165.254.138.165 +UA,IVANOFRANKIVSK,"",48.92,24.71,80.239.222.190 +US,NORTHLITTLEROCK,AR,34.7664,-92.255,173.197.194.159 +CH,LIESTAL,"",47.47,7.73,23.14.94.220 +US,PLAINVIEW,TX,34.1983,-101.7867,23.5.164.146 +MN,KHANUUL,"",48.02,114.67,92.122.215.89 +US,SMITHERS,WV,38.1675,-81.3038,184.28.17.76 +FO,THORSHAVN,"",62.02,-6.77,23.215.60.64 +IN,PUDUCHERRY,PY,11.93,79.83,124.124.252.153 +PL,STARACHOWICE,"",51.07,21.07,80.15.235.163 +US,ISHPEMING,MI,46.4126,-87.6827,65.113.249.11 +AT,THAL,"",48.23,15.40,195.145.147.107 +US,AMESBURY,MA,42.8537,-70.9439,184.25.109.200 +KZ,USTKAMENOGORSK,"",49.98,82.61,2.21.240.40 +US,ALACHUA,FL,29.8204,-82.4896,63.216.54.231 +IN,WARANGAL,AP,18.00,79.58,213.248.108.233 +CH,REGENSDORF,"",47.43,8.47,193.247.167.214 +RU,SEVERSK,"",56.62,84.88,80.239.237.93 +US,BAYVILLE,NJ,39.9119,-74.2096,184.26.44.38 +US,TOWSON,MD,39.4025,-76.6344,23.192.161.16 +US,YORKVILLE,IL,41.5984,-88.4334,23.67.60.222 +US,PURCELL,OK,34.9880,-97.4962,23.5.164.143 +US,COPPERASCOVE,TX,31.2607,-98.1131,107.14.43.29 +FI,JYVASKYLA,"",62.23,25.73,82.96.58.102 +RU,KOSTROMA,"",57.77,40.93,2.21.240.61 +CA,GIMLI,MB,50.63,-97.00,184.27.120.50 +FR,SAINTMAURICE,"",48.82,2.43,2.16.117.190 +TR,BORNOVA,"",38.45,27.23,2.16.153.150 +US,THORNDALE,PA,40.0002,-75.7594,184.26.44.40 +US,ALBION,NE,41.7470,-98.0152,198.173.2.247 +CY,STROVOLOS,"",35.15,33.34,79.140.94.243 +AT,BREGENZ,"",47.50,9.77,195.145.147.107 +CZ,DUKOVANY,"",49.08,16.20,23.62.237.138 +RU,SMOLENSK,"",54.78,32.04,2.21.240.61 +IN,MODASA,GJ,23.47,73.30,117.239.189.110 +US,CONNEAUT,OH,41.8949,-80.5816,204.93.39.36 +US,FORTGEORGEGMEADE,MD,39.0822,-76.7601,23.192.161.21 +US,HOLIDAY,FL,28.1960,-82.7256,23.33.186.101 +CA,DARTMOUTH,NS,44.67,-63.57,67.69.197.95 +US,WESTLIBERTY,KY,37.9370,-83.2694,184.27.45.150 +US,CEDARRAPIDS,IA,41.9747,-91.658,23.79.255.153 +US,WARNERROBINS,GA,32.5887,-83.6576,184.51.35.226 +AE,RASALKHAIMAH,"",25.79,55.94,195.245.125.117 +BR,BAURU,SP,-22.32,-49.07,200.174.107.42 +US,HUBBARD,OH,41.1682,-80.5712,107.14.38.217 +VN,TRUONGDINH,"",9.92,106.13,96.17.180.177 +PL,SLUBICE,"",52.37,19.95,2.22.52.102 +DE,VECHTA,NI,52.72,8.28,195.95.193.132 +FR,VIRYCHATILLON,"",48.67,2.38,2.16.117.200 +US,WESTMILFORD,NJ,41.0879,-74.3771,184.26.44.38 +DE,EMMENDINGEN,BW,48.13,7.85,195.145.147.107 +CA,FERGUS,ON,43.70,-80.37,65.116.149.102 +RS,DOLOVO,"",42.57,20.56,23.14.94.228 +CA,STONEYCREEK,ON,43.22,-79.75,72.246.43.237 +US,GROVETOWN,GA,33.5121,-82.2984,184.27.45.157 +KG,JALALABAD,"",40.93,73.00,80.239.217.231 +US,CRESTVIEW,FL,30.7849,-86.5136,184.27.45.157 +US,BEACHWOOD,OH,41.4698,-81.5121,96.17.9.14 +NP,PALPA,"",27.87,83.48,23.205.118.109 +RO,TIMIS,"",48.03,26.98,80.239.149.123 +PL,LIS,"",51.72,18.12,2.22.52.105 +RU,VOLGODONSK,"",47.51,42.15,213.155.156.206 +US,SOUTHPLAINFIELD,NJ,40.5745,-74.4149,184.28.17.76 +NO,TAFJORD,"",62.25,7.43,82.96.58.85 +TH,DHONBURI,"",13.72,100.48,110.164.11.192 +SI,GORA,"",46.13,14.80,194.25.95.225 +US,BATESBURG,SC,33.9549,-81.564,204.2.243.143 +PH,MONTE,"",18.03,120.52,58.71.107.119 +CR,DESAMPARADOS,"",9.90,-84.07,72.246.65.38 +RO,PLOIESTI,"",44.95,26.02,2.22.52.102 +SK,SLIAC,"",48.62,19.18,23.62.237.138 +US,ULYSSES,KS,37.5622,-101.308,23.215.15.9 +FR,DORDIVES,"",48.15,2.77,72.246.65.26 +US,DUARTE,CA,34.1397,-117.9765,184.50.26.201 +US,HUNTINGTOWN,MD,38.6096,-76.6075,23.192.161.21 +JP,KAWAJIMA,11,36.01,139.48,23.3.104.29 +US,STANFORD,CA,37.4162,-122.1722,23.61.195.165 +HU,KOBANYA,"",47.48,19.17,23.14.94.220 +US,RUPERT,ID,42.6416,-113.6373,67.131.104.6 +RU,SAVVA,"",54.08,43.07,213.155.156.212 +US,HOQUIAM,WA,47.0202,-123.8781,23.212.59.85 +TR,MANISA,"",38.60,27.43,193.45.15.199 +AT,MARIAENZERSDORF,"",48.10,16.28,23.74.24.66 +US,BEECHGROVE,IN,39.7156,-86.0931,23.67.60.223 +US,GLENPOOL,OK,35.9484,-96.0042,23.215.15.22 +SE,RINGON,O,57.72,11.97,2.21.240.61 +RU,CHELIABINSK,"",55.17,61.40,2.21.240.61 +US,NEWBURYPORT,MA,42.8125,-70.9023,184.25.109.200 +US,EDISON,NJ,40.5175,-74.3955,96.17.180.175 +US,HILTONHEADISLAND,SC,32.2161,-80.7525,23.61.195.165 +US,ROCKWOOD,MI,42.0725,-83.2169,23.67.60.222 +CN,MADIAN,HA,34.23,112.58,72.246.191.16 +US,WABASH,IN,40.7414,-85.8426,23.67.60.222 +US,WINSTED,MN,44.9422,-94.0752,23.74.8.24 +HK,SAIKUNG,"",22.38,114.27,184.84.239.186 +US,HILLSVILLE,VA,36.7370,-80.6935,184.29.107.20 +US,HEMPSTEAD,NY,40.7141,-73.6003,23.62.237.133 +US,BARNWELL,SC,33.2109,-81.3471,72.246.247.30 +US,CARENCRO,LA,30.3321,-92.0496,96.17.153.157 +US,GLENBURNIE,MD,39.1605,-76.5823,23.192.161.30 +PL,KIELCE,"",50.83,20.67,80.15.235.163 +US,PARKRIVER,ND,48.4562,-97.7315,63.216.54.231 +US,SORRENTO,FL,28.8172,-81.4964,23.79.240.48 +US,HURRICANE,WV,38.3842,-81.9872,184.28.17.55 +PL,MAJORAT,"",51.20,21.08,2.22.52.105 +US,CHOCOWINITY,NC,35.4436,-77.0766,63.151.29.15 +US,PARAGOULD,AR,36.0612,-90.5641,204.93.47.220 +US,WITTENBERG,WI,44.8179,-89.172,23.63.227.214 +US,CARBONDALE,IL,37.7248,-89.197,23.74.8.24 +KZ,PAVLODAR,"",52.30,76.95,213.155.156.208 +ID,KELAPAGADING,"",-6.17,106.88,23.0.162.21 +AT,TIROL,"",47.70,15.55,195.145.147.101 +US,COTTAGEGROVE,WI,43.0705,-89.1909,184.85.215.165 +US,CANFIELD,OH,41.0050,-80.7708,184.25.157.169 +CL,CONCEPCION,"",-36.83,-73.05,200.91.22.116 +US,BERTHOUD,CO,40.2947,-105.104,23.212.53.64 +US,IRWIN,PA,40.3156,-79.724,23.192.161.16 +DE,REISER,TH,51.25,10.47,195.145.147.108 +NZ,PARNELL,"",-36.87,174.78,184.28.126.7 +CA,HANNA,AB,51.63,-111.92,66.185.88.190 +US,WOODWAY,TX,31.5103,-97.2578,107.14.43.29 +CN,YINCHUAN,NX,38.47,106.27,72.246.191.16 +FR,GOLFEJUAN,"",43.57,7.08,88.221.83.140 +VE,BARQUISIMETO,"",10.07,-69.33,72.246.65.26 +US,HAVRE,MT,48.7104,-109.7919,165.254.207.117 +US,LEAVENWORTH,KS,39.2650,-95.0476,23.77.234.11 +JP,OI,11,35.85,139.52,72.246.191.16 +MT,BKARA,"",35.90,14.46,79.140.94.234 +US,HEBERSPRINGS,AR,35.6262,-92.064,23.5.164.143 +RU,MOSHKOVO,"",53.89,38.71,80.239.237.93 +US,REDLION,PA,39.8974,-76.608,23.192.161.30 +TH,PHITSANULOK,"",16.83,100.25,61.19.12.79 +US,DUFFIELD,VA,36.7086,-82.8103,23.79.240.36 +US,KAUKAUNA,WI,44.3542,-88.2601,107.14.38.224 +US,LAMAR,MO,37.5121,-94.2674,23.212.53.64 +US,WALNUTPORT,PA,40.7653,-75.56,184.26.44.38 +TR,ALAYBEY,"",38.47,27.13,193.45.15.198 +DE,ARNSTADT,TH,50.83,10.95,23.14.94.214 +US,EASTORANGE,NJ,40.7716,-74.2073,184.26.44.38 +BA,GORAZDE,"",43.67,18.98,23.14.94.228 +CH,PRATTELN,"",47.52,7.68,23.14.94.224 +RU,DON,"",52.43,35.16,2.21.240.40 +US,BURKE,VA,38.7935,-77.2718,63.130.161.239 +US,SHOREWOOD,IL,41.5083,-88.2276,23.67.60.220 +US,BETHANY,OK,35.5140,-97.6431,23.215.15.32 +CA,COQUITLAM,BC,49.27,-122.78,24.244.17.205 +EE,RAKVERE,"",59.35,26.36,217.212.227.31 +UA,NOVOTROITSKOE,"",46.95,36.66,80.239.222.169 +US,RIOVISTA,CA,38.2185,-121.7701,23.212.52.79 +US,HAYSVILLE,KS,37.5657,-97.3491,23.215.15.22 +US,MASSILLON,OH,40.8118,-81.4987,205.185.195.183 +SK,PRIEVIDZA,"",48.77,18.63,92.122.215.67 +RO,ROMANA,"",44.20,24.17,80.239.149.123 +US,CEDARCITY,UT,37.7617,-113.2197,23.61.195.150 +US,BAYVILLAGE,OH,41.4853,-81.9318,96.17.9.8 +US,ERWIN,TN,36.0829,-82.4955,23.79.240.48 +NL,TIEL,"",51.88,5.43,92.122.189.114 +DE,ESCHBACH,HE,50.35,8.53,92.122.215.89 +US,OLEAN,NY,42.0970,-78.4026,107.14.38.218 +NL,ALBLASSERDAM,"",51.87,4.67,95.101.2.122 +US,BARNESVILLE,GA,33.0291,-84.1327,72.246.247.30 +US,HAVERHILL,MA,42.7965,-71.0534,2.21.240.61 +US,LEHIGHTON,PA,40.8001,-75.751,165.254.48.155 +FR,FERRETTE,"",47.50,7.32,2.16.117.200 +GD,SAINTGEORGES,"",12.05,-61.75,23.74.2.12 +US,BELLAVISTA,AR,36.4493,-94.2399,23.215.15.9 +GB,LANGLEY,EN,51.98,0.10,88.221.87.94 +FR,SAINTANDREDESEAUX,"",48.37,-2.02,2.16.117.190 +RO,VASLUI,"",46.63,27.73,213.200.109.183 +MX,PACHUCADESOTO,HID,20.12,-98.73,201.144.215.104 +US,SHELTON,CT,41.3059,-73.1393,184.25.109.200 +US,ASHFLAT,AR,36.2067,-91.585,205.185.195.183 +UA,GONCHAROV,"",48.67,25.20,2.22.52.105 +US,BARABOO,WI,43.4869,-89.7322,184.85.215.165 +US,SWEETWATER,TX,32.5104,-100.3053,23.5.164.143 +NO,TRONDHEIM,"",63.42,10.42,2.21.240.40 +US,DOTHAN,AL,31.2035,-85.4998,23.79.240.48 +US,RUTLAND,VT,43.6369,-72.9375,184.25.109.201 +IN,PHAGWARA,PB,31.22,75.77,213.248.108.244 +UA,VINOGRADAR,"",46.67,30.35,2.22.52.105 +FR,BRUNOY,"",48.70,2.50,2.16.117.200 +FR,PERPIGNAN,"",42.68,2.88,2.16.117.190 +US,LANDOLAKES,FL,28.2463,-82.453,23.79.255.149 +MX,ANAHUAC,NLE,27.23,-100.15,187.210.208.101 +US,KEYSTONEHEIGHTS,FL,29.8670,-81.9355,23.79.240.36 +AR,VILLAMARIA,"",-34.90,-60.37,200.123.201.215 +US,HORNELL,NY,42.3231,-77.6478,107.14.38.217 +AU,MULLUMBIMBY,NSW,-28.55,153.50,202.7.177.76 +FR,BRON,"",47.17,-0.12,2.16.117.190 +US,FISHERS,IN,39.9571,-85.9923,23.67.60.220 +US,MASON,OH,39.3540,-84.3079,107.14.38.224 +BR,UBERLANDIA,MG,-18.92,-48.30,200.174.107.42 +US,BEAVERFALLS,PA,40.7641,-80.3864,23.192.161.21 +US,TAYLORSVILLE,NC,35.9243,-81.216,72.246.247.30 +US,DELPHI,IN,40.5373,-86.6356,72.247.10.237 +CK,AVARUA,"",-21.20,-159.77,23.216.10.54 +US,MEXIA,TX,31.6887,-96.511,67.131.44.154 +US,GOFFSTOWN,NH,43.0165,-71.5582,184.25.109.213 +CN,SHAOXING,ZJ,30.00,120.58,117.103.188.205 +US,HARDINSBURG,KY,37.7834,-86.4612,23.220.100.223 +GB,BROMLEY,EN,51.42,0.02,23.67.255.158 +US,GARDENDALE,AL,33.7057,-86.8471,72.246.247.5 +US,SATELLITEBEACH,FL,28.1733,-80.598,23.33.186.101 +CY,LARNACA,"",34.92,33.63,79.140.94.183 +AT,GERASDORF,"",48.28,16.47,46.33.70.97 +US,STOW,OH,41.1788,-81.4432,107.14.38.227 +US,MARSHFIELD,WI,44.6687,-90.1714,184.85.215.165 +US,POOLER,GA,32.1122,-81.2597,23.79.240.36 +PL,WLOCLAWEK,"",52.65,19.03,80.239.222.190 +CA,STEINBACH,MB,49.52,-96.68,184.25.157.155 +US,SPANISHFORK,UT,40.1192,-111.6894,23.215.15.32 +US,LAKECITY,FL,30.1899,-82.6394,23.79.240.48 +AU,BAYSWATER,VIC,-37.85,145.27,23.14.94.224 +TR,BALIKESIR,"",39.65,27.88,2.21.240.61 +US,DERBY,NY,42.6878,-78.9939,184.26.44.40 +FR,TOURS,"",47.38,0.68,2.16.117.190 +JP,IWAKUNI,35,34.15,132.18,184.51.199.145 +FR,DOUAI,"",50.37,3.07,2.16.117.200 +RO,TARGOVISTE,"",44.93,25.45,81.196.26.198 +BG,BALCHIK,"",43.42,28.17,93.186.137.230 +US,PETERSBURG,VA,37.2163,-77.4783,184.27.45.150 +DE,BEILNGRIES,BY,49.04,11.47,2.22.61.102 +CN,LIAOYANG,LN,41.23,123.10,23.5.164.143 +GB,WORTHING,EN,50.80,-0.37,23.67.255.158 +US,BLOOMFIELD,NJ,40.8099,-74.187,23.67.242.139 +US,MAYWOOD,CA,33.9888,-118.1876,184.50.26.194 +US,PELHAM,AL,33.3024,-86.8026,72.246.247.30 +US,STREATOR,IL,41.1182,-88.8294,23.74.8.24 +US,RIORICO,AZ,31.4762,-111.1242,63.226.34.181 +US,UMATILLA,FL,28.9435,-81.6854,63.148.206.235 +PH,CAGAYANDEORO,"",8.48,124.65,202.78.83.170 +US,DEFIANCE,OH,41.3548,-84.3569,107.14.38.227 +EC,AMBATO,"",-1.25,-78.62,23.74.2.12 +US,HARPERWOODS,MI,42.4389,-82.9295,69.22.154.212 +US,NAVARRE,FL,30.5228,-86.8762,96.17.153.157 +PH,MACTAN,"",12.12,123.77,63.217.232.22 +NO,BERGEN,"",60.39,5.32,23.65.29.93 +US,TAFT,CA,35.1546,-119.4343,107.14.43.29 +TR,TEKIRDAG,"",40.98,27.52,193.45.15.199 +US,RAEFORD,NC,35.0278,-79.2454,63.151.29.15 +US,ENNIS,TX,32.3479,-96.579,65.113.249.8 +JP,KASAOKA,33,34.50,133.50,23.3.104.29 +US,SOUTHHAVEN,MI,42.4049,-86.2175,23.67.60.220 +US,HARLINGEN,TX,26.2089,-97.6849,65.113.249.11 +BE,MONS,"",50.45,3.93,23.62.100.154 +US,SALKUM,WA,46.5139,-122.656,165.254.144.25 +RO,SATUMARE,"",46.33,25.37,46.33.70.104 +VN,TANLAP,"",10.92,107.18,96.17.180.155 +IN,MYLAPORE,TN,13.03,80.27,124.124.201.227 +US,PLEASANTGROVE,UT,40.3798,-111.7415,184.84.180.68 +SE,KARLSTAD,S,59.37,13.50,80.239.237.93 +US,CROCKETT,TX,31.2828,-95.4821,23.215.15.9 +US,HARBORCITY,CA,33.7982,-118.3001,184.87.195.109 +US,HIXSON,TN,35.1670,-85.2137,23.79.240.36 +NO,STAVANGER,"",58.97,5.75,217.212.227.25 +US,SANBENITO,TX,26.1784,-97.6678,184.26.93.111 +US,ATLANTICCITY,NJ,39.3648,-74.4342,23.67.242.156 +US,MIDDLEVILLAGE,NY,40.7154,-73.8794,24.143.199.188 +AU,HILLCREST,QLD,-17.37,145.60,23.62.157.32 +US,HURST,TX,32.8164,-97.1774,23.215.15.32 +IN,UDAGAMANDALAM,TN,11.40,76.70,117.239.240.96 +US,DOLTON,IL,41.6290,-87.5979,23.67.60.220 +NZ,WHANGAREI,"",-35.72,174.32,219.88.186.167 +US,FORDS,NJ,40.5421,-74.3112,23.192.161.30 +US,CORTEMADERA,CA,37.9238,-122.5131,216.246.93.44 +AT,SCHLADMING,"",47.38,13.68,46.33.70.104 +ID,SAMBU,"",1.17,103.90,118.98.42.129 +US,STILWELL,OK,35.7926,-94.6204,184.51.101.56 +ZA,MARSHALLTOWN,"",-26.20,28.08,196.37.155.136 +FR,LAGNY,"",49.08,2.75,2.20.243.45 +GB,BECKTON,EN,51.52,0.07,23.67.255.158 +AU,DARWIN,NT,-12.47,130.83,184.86.223.76 +US,PORTISABEL,TX,26.0776,-97.3389,184.26.93.111 +US,RAVENNA,OH,41.1736,-81.1686,107.14.38.227 +IR,QOM,"",34.65,50.88,92.122.215.67 +US,LINCOLNPARK,MI,42.2429,-83.1811,69.22.154.219 +US,SILSBEE,TX,30.3978,-94.1766,107.14.43.30 +US,GALLIPOLIS,OH,38.7997,-82.2553,96.17.9.14 +US,NEWROCHELLE,NY,40.9182,-73.785,23.67.242.156 +US,WILSON,NC,35.7058,-77.9227,209.18.41.23 +US,FARMERVILLE,LA,32.7394,-92.2308,96.17.153.157 +US,BAXTERSPRINGS,KS,37.0595,-94.7764,209.170.117.178 +IR,SHAHRIYAR,"",35.66,51.06,23.57.69.156 +PL,TARNOBRZEG,"",50.58,21.68,80.15.235.161 +US,LYNNHAVEN,FL,30.2384,-85.6449,184.84.180.97 +KR,CHUNGNAM,"",36.27,128.02,125.56.214.169 +ID,SOSIAL,"",-9.49,124.85,23.0.162.40 +US,ROYSECITY,TX,32.9603,-96.3618,23.5.164.143 +IN,RANIPPETTAI,TN,12.93,79.33,117.239.240.96 +US,HARWOOD,MD,38.8654,-76.6145,23.192.161.30 +US,CHICAGOHEIGHTS,IL,41.5054,-87.5907,23.63.227.227 +US,DRAPER,UT,40.5003,-111.8772,184.84.180.98 +US,WOODRIVER,IL,38.8622,-90.0969,204.93.47.216 +US,STRUM,WI,44.5831,-91.3728,23.74.8.8 +JP,OTSUKA,32,35.38,133.27,104.74.70.98 +US,NEWTOWNSQUARE,PA,39.9794,-75.4369,23.74.8.8 +US,GRAYSLAKE,IL,42.3279,-88.0546,107.14.38.224 +US,SMITHTON,MO,38.6141,-93.1156,65.113.249.11 +US,WHITEHALL,MI,43.3852,-86.3162,23.63.227.227 +US,GULFSHORES,AL,30.2490,-87.8145,184.51.35.215 +IR,KAMYARAN,"",34.79,46.94,23.14.94.214 +US,CENTRE,AL,34.0680,-85.5772,23.79.240.36 +JP,KAKEGAWA,22,34.77,138.02,23.3.104.29 +BG,BURGAS,"",42.50,27.47,213.248.108.233 +US,HERCULANEUM,MO,38.2616,-90.3893,96.17.14.15 +FR,PFAFFENHOFFEN,"",48.85,7.62,2.16.117.190 +US,CANDLER,NC,35.5160,-82.718,23.79.240.48 +US,ABITASPRINGS,LA,30.4796,-89.9372,23.215.15.22 +FR,COURBEVOIE,"",48.54,2.15,2.16.117.190 +KR,HANGYANG,"",35.41,127.84,125.56.214.149 +US,MOREHEAD,KY,38.2298,-83.4396,184.51.101.56 +CN,DANJIANGKOU,HB,32.54,111.51,63.233.61.151 +US,MUSKEGO,WI,42.8864,-88.1268,65.113.249.8 +IR,MALAYER,"",34.29,48.82,80.239.149.123 +IN,ANNANAGAR,TN,13.08,80.22,23.205.118.109 +RU,KOMSOMOLSKNAAMURE,"",50.56,137.00,2.21.240.40 +US,BARTOW,FL,27.8693,-81.7818,165.254.205.13 +KN,BASSETERRE,"",17.30,-62.72,184.26.44.38 +RU,SIBIR,"",59.13,48.55,2.21.240.61 +DE,OHL,NW,50.98,7.38,194.25.95.214 +US,LAKESTATION,IN,41.5743,-87.2638,23.67.60.222 +JP,SAKURA,12,35.72,140.23,23.61.250.113 +RO,MEDIAS,"",46.17,24.35,81.196.26.237 +US,NEWTONFALLS,OH,41.1752,-80.9706,107.14.38.218 +US,BRANSON,MO,36.6436,-93.2185,23.5.164.146 +US,LAVERGNE,TN,36.0144,-86.5554,23.212.53.75 +CH,NOIRMONT,"",47.22,6.95,213.254.212.98 +US,WESTBROOK,ME,43.7142,-70.3494,107.14.38.227 +IN,ROORKEE,UL,29.87,77.88,96.17.182.136 +FR,CERGYPONTOISE,"",49.00,2.03,2.20.243.42 +US,SAPULPA,OK,35.9978,-96.1373,23.215.15.9 +LI,VADUZ,"",47.13,9.52,195.27.155.193 +US,THREERIVERS,MI,41.9815,-85.6518,23.67.60.220 +US,MURRAY,KY,36.6180,-88.2562,107.14.38.224 +US,YANKTON,SD,42.8878,-97.454,23.63.227.227 +SE,KARLSKRONA,K,56.17,15.58,23.65.29.106 +CA,NELSON,BC,49.48,-117.28,184.27.179.187 +US,KODAK,TN,35.9712,-83.6158,72.246.247.30 +US,TAYLORS,SC,34.9846,-82.3279,72.246.247.5 +US,ELCERRITO,CA,37.9232,-122.2937,23.212.52.79 +SK,HRKOVCE,"",48.08,18.92,23.62.237.135 +US,GETTYSBURG,PA,39.8288,-77.2253,23.192.161.16 +US,FAIRMONT,WV,39.4675,-80.064,23.192.161.16 +US,BROOKHAVEN,MS,31.5898,-90.4722,165.254.138.175 +US,EVERGREENPARK,IL,41.7213,-87.7012,107.14.38.227 +US,WASHINGTONCOURTHOUSE,OH,39.5227,-83.4503,107.14.38.224 +US,HARTLAND,WI,43.1384,-88.3524,65.113.249.11 +KR,DAEGU,"",35.87,128.60,125.56.214.147 +JP,MIYAZAKI,45,31.90,131.43,23.3.104.15 +CA,CHARLOTTETOWN,PE,46.23,-63.13,23.220.148.122 +US,STANDISH,ME,43.8159,-70.4792,23.61.195.150 +US,LADYLAKE,FL,28.9173,-81.9232,23.79.240.36 +LC,CASTRIES,"",14.00,-61.00,23.33.186.134 +CN,NANTONG,JS,32.03,120.87,184.50.87.178 +US,BREWTON,AL,31.1650,-87.0243,96.17.153.162 +ID,MAKASAR,"",-6.28,106.87,184.27.179.159 +AT,RUM,"",47.28,11.45,195.145.147.108 +US,ORTING,WA,46.9930,-122.097,67.131.104.14 +US,AVONPARK,FL,27.5936,-81.3646,184.27.45.150 +US,MINNETONKA,MN,44.9156,-93.484,23.67.60.222 +US,WINDOM,MN,43.9264,-95.2282,23.63.227.227 +US,NORTHMIAMIBEACH,FL,25.9339,-80.1467,165.254.205.13 +US,VINCENNES,IN,38.6298,-87.5042,23.63.227.214 +US,PAYSON,UT,40.0019,-111.732,184.84.180.98 +SE,JARNA,AB,59.10,17.57,2.21.240.40 +JP,KAMO,12,35.50,140.12,184.51.199.132 +EE,KOHTLAJARVE,"",59.40,27.27,213.155.156.207 +US,CODY,WY,44.5150,-109.5903,23.63.227.223 +PL,TRZESZCZYN,"",53.55,14.52,92.122.189.114 +AU,LISMORE,NSW,-28.80,153.27,104.72.70.95 +BT,THIMPHU,"",27.48,89.60,23.76.205.111 +GB,SWANSEA,WA,51.63,-3.97,88.221.87.112 +RO,COMANESTI,"",44.42,24.13,88.221.93.150 +CA,UCLUELET,BC,48.93,-125.52,24.244.17.197 +FR,VER,"",49.10,2.68,23.200.87.59 +US,CATASAUQUA,PA,40.6570,-75.4675,184.29.107.20 +US,CALIFORNIA,MO,38.6124,-92.5168,23.79.255.153 +FR,TOURNONSURRHONE,"",45.07,4.83,2.16.117.190 +US,NEWKENSINGTON,PA,40.5657,-79.707,23.192.161.30 +MW,LILONGWE,"",-13.98,33.78,41.193.163.45 +US,GREENEVILLE,TN,36.1512,-82.8404,23.79.240.48 +US,CAVECITY,KY,37.1209,-85.9332,65.113.249.11 +JP,YOSIDA,38,33.27,132.55,96.7.251.95 +GF,CAYENNE,"",4.93,-52.33,72.246.65.23 +US,DANBURY,CT,41.3768,-73.4601,23.67.60.220 +CM,DOUALA,"",4.05,9.70,2.16.158.137 +US,PASSAIC,NJ,40.8575,-74.1285,184.26.44.40 +US,ATKINS,IA,41.9918,-91.8933,65.113.249.11 +ES,ACORUNA,"",43.37,-8.38,92.122.189.85 +US,WYANDOTTE,MI,42.1883,-83.1904,69.22.154.215 +US,ANDREWS,TX,32.3051,-102.6378,23.5.164.146 +US,ASPEN,CO,39.1256,-106.7972,184.84.180.68 +TR,FATIH,"",41.02,28.94,217.212.227.25 +US,BRISTOW,VA,38.7380,-77.5569,184.28.17.55 +FR,BRIGNOLES,"",43.40,6.07,2.16.117.190 +US,WESTLINN,OR,45.3523,-122.6694,23.212.59.63 +US,CROFTON,MD,39.0135,-76.6813,23.67.242.139 +FR,ANGERS,"",47.47,-0.55,2.16.117.190 +BO,LAPAZ,"",-16.50,-68.15,200.91.22.116 +AU,TEMPLESTOWELOWER,VIC,-37.77,145.12,23.62.224.33 +US,KELSO,WA,46.1383,-122.7605,23.212.59.63 +PG,WAIGANI,"",-9.43,147.17,23.62.157.32 +US,BRONXVILLE,NY,40.9389,-73.8308,69.31.77.200 +US,NORTHCONWAY,NH,44.0406,-71.0915,107.14.38.217 +US,CATSKILL,NY,42.2274,-73.9283,184.29.107.38 +US,OAKFOREST,IL,41.6061,-87.7549,107.14.38.218 +PL,NOWYTARG,"",53.90,19.20,80.239.255.214 +US,PHILOMATH,OR,44.6158,-123.5018,23.212.59.63 +US,HARROGATE,TN,36.5673,-83.5418,184.25.157.169 +TH,PATTAYA,"",12.93,100.88,61.19.12.79 +US,PORTHUENEME,CA,34.1619,-119.2034,23.216.10.48 +US,DEARBORNHEIGHTS,MI,42.2751,-83.2624,23.67.60.222 +US,OELWEIN,IA,42.7073,-91.8755,184.27.120.50 +US,METTER,GA,32.4031,-82.0735,8.18.43.219 +ES,ARTES,"",41.80,1.95,2.20.44.111 +US,STONYBROOK,NY,40.9035,-73.127,209.170.113.240 +CN,YICHUN,HL,47.70,128.90,184.50.87.178 +TM,ASHGABAT,"",37.95,58.38,117.103.188.218 +FR,SARCELLES,"",49.00,2.38,2.16.117.190 +US,DONNA,TX,26.1405,-98.071,184.26.93.111 +IR,PISHGAMAN,"",37.27,48.44,77.67.27.235 +JP,NARA,29,34.68,135.83,117.104.139.162 +SK,SKALICA,"",48.85,17.23,23.62.237.137 +RO,HUNEDOARA,"",45.75,22.90,81.196.26.236 +US,SEALY,TX,29.7835,-96.2064,96.16.7.120 +US,GREENRIVER,WY,41.9520,-109.6565,63.217.8.168 +US,BAYSPRINGS,MS,31.9429,-89.2,69.31.59.63 +US,SILERCITY,NC,35.7397,-79.4342,184.51.35.226 +IT,PIGNONE,"",44.17,9.72,2.18.240.95 +FR,ILLKIRCHGRAFFENSTADEN,"",48.53,7.72,2.16.117.200 +AT,ORTIMINNKREIS,"",47.90,13.78,195.145.147.109 +RU,ISKRA,"",55.16,36.89,80.239.237.84 +US,LONGWOOD,FL,28.7075,-81.3526,23.34.56.142 +JP,MITANI,36,33.93,134.48,23.3.104.29 +DK,MARIAGER,"",56.65,10.00,23.65.29.106 +US,MOUNTHOLLY,NJ,39.9896,-74.8021,184.26.44.40 +IN,JORHAT,AS,26.75,94.22,124.124.252.165 +DE,APEN,NI,53.22,7.80,92.122.207.164 +PG,LAE,"",-6.73,147.00,23.62.157.32 +US,HINSDALE,NH,42.8109,-72.499,184.25.109.213 +US,DODGEVILLE,WI,42.9917,-90.1451,23.74.8.24 +IT,MILANESE,"",38.20,15.73,193.45.15.198 +DE,HANAU,HE,50.13,8.92,23.14.94.214 +RU,KHANTYMANSIYSK,"",61.00,69.10,80.239.217.238 +US,HAZARD,KY,37.2415,-83.2013,63.216.54.231 +BR,JUIZDEFORA,MG,-21.75,-43.35,184.25.157.155 +US,LYONS,KS,38.3042,-98.1167,23.215.15.9 +TR,ISIK,"",39.02,28.37,2.20.142.173 +RO,FOCSANI,"",45.70,27.18,81.196.26.237 +CZ,HAVEL,"",49.08,14.83,2.20.142.166 +ID,SLIPI,"",-6.20,106.78,23.0.162.21 +US,CEREDO,WV,38.3954,-82.5576,209.48.37.183 +US,ORELAND,PA,40.1145,-75.1853,23.67.242.139 +MX,CUAUTITLAN,MEX,19.67,-99.18,201.144.215.103 +US,TRUMBULL,CT,41.2599,-73.2099,65.113.249.11 +CN,NINGDE,FJ,26.66,119.52,184.50.87.176 +SE,KALMAR,H,56.67,16.37,213.155.156.207 +JP,KAWAGUCHI,11,35.81,139.72,23.3.104.16 +RU,ODIN,"",60.08,55.12,2.21.240.61 +DE,GEISELGASTEIG,BY,48.07,11.55,23.14.94.214 +KR,NAEDONG,"",37.27,126.81,80.239.237.230 +US,GRANDISLAND,NE,40.9005,-98.3297,204.93.47.220 +RU,MAGNITOGORSK,"",53.45,59.07,80.239.237.80 +US,GODFREY,IL,38.9622,-90.2202,96.17.14.31 +US,WEST,TX,31.7636,-97.1357,23.5.164.146 +US,SAGHARBOR,NY,40.9692,-72.306,69.31.77.208 +US,DENVILLE,NJ,40.8897,-74.4855,184.26.44.38 +US,TAKOMAPARK,MD,38.9819,-77.0006,23.192.161.16 +US,COLUMBIACITY,IN,41.1479,-85.4772,65.113.249.8 +CA,NEWMARKET,ON,44.05,-79.45,72.246.43.237 +US,WILLOWGROVE,PA,40.1476,-75.1216,23.192.161.16 +US,KAMRAR,IA,42.3937,-93.7196,23.74.8.8 +US,KENDRICK,ID,46.6455,-116.5458,165.254.144.25 +US,PALMERTON,PA,40.8306,-75.5685,165.254.48.150 +SN,DAKAR,"",14.67,-17.43,213.200.109.173 +US,BONITASPRINGS,FL,26.3319,-81.7522,204.93.43.168 +KR,SAMCHOK,"",37.44,129.17,125.56.214.147 +US,SHINGLESPRINGS,CA,38.6203,-120.9818,23.61.195.165 +KE,MERU,"",0.05,37.65,41.193.163.45 +US,ELKINS,WV,38.9430,-79.8268,96.17.9.14 +JP,WAGO,06,38.32,140.17,23.3.104.16 +IR,POLEFASA,"",29.48,52.64,96.17.182.130 +SE,HANINGE,AB,59.10,18.08,217.212.227.25 +US,YULEE,FL,30.6324,-81.6068,184.51.145.22 +US,ROCHELLE,IL,41.9424,-89.0653,23.67.60.220 +US,CARPENTERSVILLE,IL,42.1252,-88.2633,23.67.60.222 +BD,RAMNA,"",23.73,90.40,23.75.23.135 +US,WILLISTON,FL,29.4056,-82.488,23.74.2.12 +US,HALEYVILLE,AL,34.2053,-87.5643,184.27.45.157 +JP,OBIHIRO,01,42.92,143.20,210.175.5.180 +SE,JONKOPING,F,57.78,14.18,82.96.58.102 +CA,VALDOR,QC,48.12,-77.77,67.69.197.95 +US,ROSLINDALE,MA,42.2845,-71.1256,23.67.244.248 +AR,TUCUMAN,"",-26.82,-65.22,200.123.201.219 +US,MILLERSBURG,OH,40.5444,-81.851,65.113.249.11 +FR,LAGARENNECOLOMBES,"",48.90,2.25,2.16.117.190 +US,HUNKER,PA,40.2070,-79.5798,23.192.161.21 +US,CROWLEY,LA,30.2290,-92.3861,23.215.15.9 +MH,MAJURO,"",7.10,171.38,96.7.251.97 +US,OSWEGO,IL,41.6565,-88.316,184.27.120.50 +KR,INCHON,"",37.45,126.73,125.56.214.147 +US,FAIRLAWN,NJ,40.9359,-74.1174,184.26.44.38 +CA,RICHMONDHILL,ON,43.87,-79.43,72.246.43.237 +DE,MUNCHEN,BY,49.55,11.58,23.14.94.228 +EC,LAGOAGRIO,"",0.08,-76.88,200.110.126.67 +RO,ARAD,"",46.18,21.32,80.239.149.123 +NO,PORSGRUNN,"",59.15,9.67,2.21.240.40 +US,MARATHON,FL,24.7161,-81.0717,23.79.240.48 +US,MOORHEAD,MN,46.9239,-96.7135,165.254.114.164 +JP,MIHARA,34,34.40,133.08,117.104.139.162 +US,ELLIJAY,GA,34.6692,-84.4462,184.28.127.55 +TR,ERZURUM,"",39.92,41.28,193.45.15.198 +US,KEOKUK,IA,40.4274,-91.4507,23.67.60.223 +US,MOUNTWASHINGTON,KY,38.0404,-85.559,63.216.54.236 +KZ,TARAZ,"",42.90,71.37,2.20.142.173 +US,MORRILTON,AR,35.2270,-92.6879,23.79.240.48 +US,CRYSTALLAKE,IL,42.2766,-88.31,23.67.60.223 +US,BEVERLY,MA,42.5685,-70.8619,184.25.109.213 +RU,MAGADAN,"",59.57,150.80,72.246.184.84 +US,BELVIDERE,IL,42.2430,-88.8419,23.67.60.220 +RO,BAIAMARE,"",47.67,23.58,81.196.26.231 +US,BANDON,OR,43.0374,-124.3662,184.27.179.187 +US,COPLAY,PA,40.6874,-75.5488,184.26.44.38 +US,OBERLIN,OH,41.2855,-82.2459,184.27.45.157 +CA,ORILLIA,ON,44.60,-79.42,72.246.43.215 +US,ROMEOVILLE,IL,41.6509,-88.0865,23.67.60.222 +US,LUVERNE,AL,31.6954,-86.2748,184.51.35.215 +GB,STIRLING,SC,56.12,-3.95,88.221.87.94 +US,PRIORLAKE,MN,44.6768,-93.4069,23.212.59.85 +US,PLUMMER,ID,47.3045,-116.8787,184.27.179.159 +FR,MOURS,"",49.13,2.27,2.16.117.190 +UA,BELAYATSERKOV,"",49.78,30.12,92.122.189.114 +DK,FREDERIKSHAVN,"",57.43,10.53,23.65.29.106 +NP,JAWALAKHEL,"",27.67,85.32,23.205.118.109 +US,ROCKSPRINGS,WY,41.6045,-108.9543,23.212.53.75 +CD,LUBUMBASHI,"",-11.67,27.47,23.3.15.22 +HU,KAPUVAR,"",47.60,17.03,80.157.150.192 +US,TEHACHAPI,CA,35.1338,-118.5522,184.26.93.111 +GB,WOKING,EN,51.32,-0.53,23.212.108.28 +IN,SOLAPUR,MH,17.68,75.92,23.205.118.106 +FR,SAINTVALERYENCAUX,"",49.87,0.73,2.16.117.190 +US,JONESTOWN,PA,40.4723,-76.5465,23.192.161.30 +MX,ZAMORADEHIDALGO,MIC,19.98,-102.27,23.215.15.9 +DE,GARMISCHPARTENKIRCHEN,BY,47.50,11.10,2.16.217.211 +US,MCCARR,KY,37.6155,-82.1695,184.27.45.157 +FR,SETE,"",43.40,3.68,88.221.15.111 +US,FARMVILLE,NC,35.5541,-77.5679,72.246.247.30 +US,CORALVILLE,IA,41.7135,-91.6243,205.185.195.170 +GB,CROY,SC,57.52,-4.03,23.67.255.106 +IL,SHEFER,"",32.94,35.43,212.25.69.136 +DE,BILSTEIN,NW,51.10,8.02,194.25.95.219 +US,GLADWIN,MI,44.0805,-84.4824,23.63.227.221 +US,CLANTON,AL,32.8085,-86.6769,72.246.247.30 +CN,KASHI,XJ,39.48,75.97,117.104.139.162 +US,SEMMES,AL,30.7548,-88.2659,96.17.153.162 +US,LAPWAI,ID,46.4250,-116.755,184.27.179.187 +AU,PARRAMATTA,NSW,-33.82,151.00,104.72.70.96 +FR,BLOIS,"",47.58,1.33,2.16.117.190 +CA,LEVIS,QC,46.80,-71.17,67.69.197.106 +US,OLIVEBRANCH,MS,34.9420,-89.5387,23.212.53.75 +US,OAKWOOD,IL,40.1323,-87.8022,23.74.8.8 +IN,BHAVNAGAR,GJ,21.77,72.15,92.122.215.67 +US,BLUEBELL,PA,40.1575,-75.2796,23.67.242.139 +US,LEONARDTOWN,MD,38.2757,-76.6352,208.185.55.117 +US,QUINTON,VA,37.5257,-77.1511,23.220.148.108 +US,LOUISBURG,KS,38.5671,-94.6773,23.215.15.22 +ZA,LOCATION,"",-29.33,21.15,196.37.155.135 +US,MONESSEN,PA,40.1512,-79.882,184.26.44.40 +US,REHOBOTHBEACH,DE,38.7115,-75.1086,23.67.242.139 +KR,MASAN,"",37.95,127.32,61.111.58.222 +PH,INTRAMUROS,"",14.60,120.97,23.76.205.90 +ES,MARCHENA,"",38.18,-2.50,213.248.113.118 +US,GRUNDY,VA,37.3014,-82.1027,184.27.45.162 +US,COSHOCTON,OH,40.2085,-81.7893,96.17.9.14 +US,PEABODY,MA,42.5338,-70.9728,184.25.109.196 +DE,SOLINGEN,NW,51.18,7.08,80.157.150.197 +US,CARMEL,NY,41.4470,-73.7115,184.25.109.200 +BE,VEURNE,"",51.07,2.67,46.33.74.161 +FI,KAUNIAINEN,"",60.22,24.74,193.184.164.237 +US,GRANDLEDGE,MI,42.7448,-84.7632,65.113.249.11 +US,FROSTBURG,MD,39.6524,-78.9473,65.121.209.133 +AU,COLO,NSW,-33.43,150.83,23.62.8.25 +DE,SINDELFINGEN,BW,48.70,9.02,23.14.94.228 +US,BURKBURNETT,TX,34.0937,-98.61,107.14.36.199 +US,MUSTANG,OK,35.3779,-97.7427,23.215.15.9 +US,FRANKLINLAKES,NJ,41.0086,-74.2082,23.67.242.139 +CA,KANATA,ON,45.33,-75.90,67.69.197.95 +US,FRUITLAND,MD,38.3183,-75.6331,23.192.161.16 +JP,MITAKA,13,35.68,139.55,23.3.104.29 +US,HOTCHKISS,CO,38.8373,-107.7837,23.74.8.8 +US,NEWINGTON,CT,41.6870,-72.7308,72.247.10.237 +CZ,KRALUPYNADVLTAVOU,"",50.23,14.32,23.74.24.69 +US,PICAYUNE,MS,30.5854,-89.6932,96.17.153.162 +CN,ZHUHAI,GD,22.28,113.57,184.50.87.178 +NO,TROMSO,"",69.67,18.97,2.21.240.40 +AT,RIEZLERN,"",47.37,10.18,92.122.189.114 +KR,CHONJU,"",35.82,127.15,61.111.58.43 +US,GRANDBLANC,MI,42.9173,-83.6285,65.113.249.11 +BA,LUKAVAC,"",43.68,18.27,2.20.142.166 +FR,MONTROUGE,"",48.82,2.32,2.16.117.200 +GB,PAPWORTH,EN,52.23,-0.12,23.67.255.106 +RU,NOVOKUZNETSK,"",53.75,87.10,2.21.240.40 +US,ELMACERO,CA,38.5361,-121.6397,65.113.249.11 +US,CHINAGROVE,NC,35.5831,-80.6086,209.18.41.27 +US,ANSON,TX,32.7550,-99.9177,23.215.15.9 +US,CUTOFF,LA,29.5615,-90.2815,23.212.53.75 +AT,LEOBERSDORF,"",47.92,16.22,195.145.147.109 +FR,VILLENEUVESAINTGEORGES,"",48.73,2.45,2.16.117.190 +MY,KLIAS,"",5.43,115.63,23.198.99.130 +PY,ASUNCION,"",-25.27,-57.67,177.159.159.51 +DE,LUEDENSCHEID,NW,51.22,7.62,195.95.193.134 +US,WINNER,SD,43.2923,-99.8934,23.63.227.214 +US,COUNCILGROVE,KS,38.6824,-96.5126,23.215.15.22 +RU,KASHIRA,"",54.84,38.17,80.239.222.190 +US,PALOSVERDESPENINSULA,CA,33.7772,-118.3685,184.50.26.194 +US,PILOTPOINT,TX,33.3456,-96.9066,23.5.164.143 +US,TOCCOA,GA,34.5647,-83.3246,204.2.243.135 +US,ALCOA,TN,35.7840,-83.9837,23.79.240.36 +JP,TOCHIGI,09,36.38,139.73,202.239.172.99 +IL,ROSHHAAYIN,"",32.09,34.95,82.102.137.148 +TH,BANGCHAK,"",13.68,100.58,180.180.251.217 +US,BUFFALOVALLEY,TN,36.1821,-85.7574,23.79.240.48 +PK,SUKKUR,"",27.70,68.87,23.5.165.167 +US,KENNETTSQUARE,PA,39.8638,-75.7134,23.62.238.220 +IN,RAJAMPET,AP,17.62,78.08,23.205.118.106 +RU,MEGION,"",61.05,76.10,80.239.237.80 +PT,CALDAS,"",41.53,-8.47,195.22.14.133 +US,JAY,OK,36.4327,-94.7494,23.215.15.9 +CN,QINGDAO,SD,36.08,120.34,117.104.138.235 +US,MORROW,GA,33.5846,-84.3286,23.212.53.74 +IN,DIGBOI,AS,27.38,95.62,96.17.182.136 +TZ,DODOMA,"",-7.28,36.35,196.37.155.134 +TW,HSINCHU,"",24.80,120.97,61.220.62.171 +CN,ZUNYI,GZ,27.69,106.91,72.246.191.16 +FR,BURESSURYVETTE,"",48.70,2.17,2.16.117.190 +US,AMITYVILLE,NY,40.6858,-73.4152,23.67.242.139 +US,WESTFORD,MA,42.5863,-71.4398,165.254.48.142 +CN,DATONG,SX,40.04,113.60,72.246.191.16 +US,HIDALGO,TX,26.0932,-98.2413,63.233.112.199 +US,WESTMEMPHIS,AR,35.1461,-90.1892,23.212.53.75 +FR,NIORT,"",46.32,-0.47,2.16.117.200 +US,EASTLAKE,OH,41.6454,-81.4495,96.17.9.8 +RO,HUSI,"",46.68,28.07,81.196.26.237 +CO,CALI,"",3.45,-76.52,200.14.44.100 +US,PARSONS,KS,37.3363,-95.2625,174.76.226.117 +FR,PLESSISBOUCHARD,"",49.00,2.23,2.20.243.45 +US,BORGER,TX,35.7207,-101.246,96.16.7.120 +US,CHEROKEE,IA,42.7282,-95.5804,165.254.207.111 +US,MONETT,MO,36.9016,-93.938,23.5.164.143 +AU,CROWSNEST,NSW,-33.83,151.20,104.72.70.95 +FR,AUCAMVILLE,"",43.80,1.22,2.16.117.200 +CA,LANCIENNELORETTE,QC,46.78,-71.38,67.69.197.106 +US,CHAPMANVILLE,WV,37.9307,-82.0853,209.48.37.183 +US,GUNTERSVILLE,AL,34.3002,-86.3298,204.2.243.135 +NZ,TORBAY,"",-36.69,174.75,219.88.186.167 +US,FOLEY,AL,30.3794,-87.7151,63.151.29.12 +EC,PUYO,"",-1.47,-77.98,72.164.253.68 +US,LAUGHLIN,NV,35.1676,-114.5723,165.254.144.32 +IT,ALZATE,"",45.57,8.58,95.101.34.109 +US,UHRICHSVILLE,OH,40.3767,-81.2875,107.14.38.217 +LT,ANYKSCIAI,"",55.53,25.10,217.212.227.31 +US,NORTHROYALTON,OH,41.3138,-81.7452,107.14.38.224 +IN,BHILWARA,RJ,25.35,74.63,23.14.94.214 +CZ,KROMERIZ,"",49.30,17.40,23.62.237.137 +IR,AZAD,"",36.53,48.52,96.17.182.130 +GB,TADWORTH,EN,51.28,-0.23,23.212.108.28 +RU,POKROVKA,"",56.27,36.93,96.7.251.95 +CN,HUZHOU,ZJ,30.87,120.10,117.103.188.218 +US,SUMNER,WA,47.2034,-122.2395,67.131.104.6 +US,HOTSPRINGS,SD,43.3460,-103.4837,23.63.227.227 +US,PAHRUMP,NV,36.2552,-116.0393,67.131.104.6 +US,ANOKA,MN,45.2924,-93.4325,23.67.60.222 +US,HOWELL,NJ,40.1478,-74.2133,184.26.44.38 +US,HERMON,NY,44.4225,-75.2101,165.254.35.197 +US,KENAI,AK,60.7681,-150.4457,165.254.1.206 +IR,MASHHAD,"",36.30,59.60,96.17.182.136 +US,ESCANABA,MI,45.7785,-87.1788,184.85.215.165 +US,SCHERTZ,TX,29.5872,-98.2801,184.26.93.116 +FR,LYS,"",47.35,3.60,88.221.15.110 +NO,LARVIK,"",59.07,10.00,2.21.240.61 +DE,BAU,NW,51.15,6.32,194.25.95.212 +US,PIPESTONE,MN,44.0660,-96.3302,23.61.195.163 +ID,PONTIANAK,"",-0.03,109.33,23.0.162.40 +AT,EGG,"",47.52,16.22,46.33.70.97 +DE,MELSUNGEN,HE,51.13,9.55,195.145.147.101 +IT,NOVARA,"",45.47,8.63,195.22.200.240 +US,JAMESTOWN,NY,42.0766,-79.2554,63.216.54.229 +US,JEANNETTE,PA,40.3273,-79.6141,63.216.54.216 +US,STORRSMANSFIELD,CT,41.8004,-72.2476,165.254.202.96 +US,FLEMINGSBURG,KY,38.4360,-83.6931,63.216.54.231 +NO,SKIEN,"",59.20,9.60,2.21.240.61 +US,FLOMATON,AL,31.1088,-87.2802,67.131.104.6 +PL,JAROSLAW,"",50.02,22.68,2.22.52.102 +US,GUERNSEY,WY,42.2368,-104.7818,107.14.32.235 +US,ELY,MN,48.0461,-92.0295,23.63.227.223 +NO,BRUMUNDDAL,"",60.88,10.93,2.21.240.40 +AT,KUFSTEIN,"",47.58,12.17,80.239.237.231 +US,EMERYVILLE,CA,37.8359,-122.2848,23.61.195.166 +US,PALESTINE,TX,31.7706,-95.5987,209.18.41.23 +RU,BUZULUK,"",52.81,40.23,80.239.237.80 +US,MUNISING,MI,46.4479,-86.4779,23.79.255.153 +US,NICHOLASVILLE,KY,37.8809,-84.5734,63.216.54.231 +IE,LIMERICK,"",52.66,-8.62,88.221.222.34 +US,CENTERMORICHES,NY,40.8046,-72.7931,184.26.44.38 +US,HARTFORDCITY,IN,40.4568,-85.3505,23.212.53.64 +US,THEODORE,AL,30.5153,-88.1489,96.17.153.157 +AT,PITTEN,"",47.72,16.18,195.145.147.108 +CZ,HOSTING,"",49.02,15.90,23.62.237.133 +AT,EGGELSBERG,"",48.08,13.00,195.145.147.108 +TW,KAOHSIUNG,"",22.63,120.28,61.220.62.175 +US,SEQUIM,WA,48.0015,-123.0905,184.27.179.181 +US,SIOUXCENTER,IA,43.0841,-96.2145,205.185.195.183 +US,SOUTHPORTLAND,ME,43.6292,-70.2915,107.14.38.218 +SE,NORSJO,X,61.72,16.30,80.239.217.238 +US,INDIANORCHARD,MA,42.1526,-72.5046,184.25.109.200 +US,HAZLEHURST,GA,31.8468,-82.5686,72.246.247.5 +US,NAVASOTA,TX,30.3670,-96.0045,23.212.53.64 +US,AMORY,MS,33.9755,-88.4422,23.220.100.223 +AR,LAPLATA,"",-34.93,-57.95,190.98.167.230 +CZ,NOVAVES,"",50.22,14.53,23.62.237.138 +PL,BOLESLAWIEC,"",51.20,18.20,2.22.52.105 +CA,LLOYDMINSTER,SK,53.28,-110.00,184.150.187.241 +FR,VALENCE,"",44.93,4.90,81.52.201.83 +DE,HOLZMINDEN,NI,51.82,9.45,195.95.193.150 +US,PUNTAGORDA,FL,26.9089,-82.0431,23.79.240.48 +MY,SERDANG,"",3.03,101.72,23.15.10.112 +PH,MUNTINLUPA,"",14.38,121.05,63.217.232.22 +MK,STRUMICA,"",41.44,22.64,23.74.24.66 +HU,SZOMBATHELY,"",47.23,16.62,80.157.150.169 +US,LONSDALE,MN,44.4527,-93.4244,23.63.227.227 +FI,HALLI,"",61.87,24.83,80.239.237.93 +DE,UNTERWELLENBORN,TH,50.65,11.43,92.122.215.89 +UA,SEVERODONETSK,"",48.95,38.50,213.155.156.207 +DE,TAXIS,BW,48.70,10.37,80.157.170.154 +US,WHARTON,TX,29.2926,-96.034,96.16.7.101 +US,LATROBE,PA,40.2834,-79.4033,23.192.161.21 +US,COLOMA,MI,42.2090,-86.3279,184.27.120.50 +CA,PRINCEALBERT,SK,53.20,-105.75,184.150.187.237 +US,FALLON,NV,39.5809,-118.3335,209.116.151.185 +CN,FENGTAI,BJ,39.84,116.29,184.51.199.145 +GB,CIRENCESTER,EN,51.73,-1.98,23.67.71.131 +RO,NASAUD,"",47.28,24.40,77.67.27.250 +RU,KOMBINAT,"",50.83,37.82,80.239.222.169 +CR,CARTAGO,"",9.87,-83.92,72.164.253.68 +US,ELMCITY,NC,35.8063,-77.8487,209.170.113.123 +IN,BENGALURU,KA,12.98,77.58,96.17.182.136 +SA,RADWA,"",26.72,50.08,79.140.94.254 +TH,NONTHABURI,"",13.83,100.48,110.164.253.209 +AR,CALETAOLIVIA,"",-46.43,-67.53,190.98.167.230 +US,TUSKEGEE,AL,32.4242,-85.6518,23.63.227.214 +US,PRESCOTTVALLEY,AZ,34.6100,-112.3153,63.226.34.173 +US,CLEBURNE,TX,32.2789,-97.4607,96.16.7.101 +US,KING,NC,36.3197,-80.3548,209.18.41.23 +JP,ISHIKAWA,07,37.15,140.45,23.61.250.113 +US,DIMMITT,TX,34.5255,-102.2563,23.74.8.24 +RU,CHEKHOV,"",55.15,37.48,2.22.52.101 +UA,VOZNESENSK,"",47.70,31.45,2.20.142.173 +JP,IWAKI,07,37.05,140.88,72.246.184.84 +US,HARLAN,IA,41.6064,-95.2684,63.216.54.231 +US,GLENDALEHEIGHTS,IL,41.9203,-88.081,23.74.8.8 +CN,LHASA,XZ,29.65,91.10,184.84.239.186 +HK,TSIMSHATSUI,"",22.30,114.17,23.76.205.111 +FR,LEROURET,"",43.68,7.02,63.80.12.205 +US,DUNDEE,IL,42.1081,-88.3234,107.14.38.218 +IN,VIZIANAGARAM,AP,18.12,83.42,117.239.240.76 +US,FENTON,MO,38.5035,-90.4616,96.17.14.31 +US,FORTPAYNE,AL,34.4140,-85.7188,23.220.100.223 +SE,ORE,AC,63.55,19.68,2.21.240.40 +AU,PYMBLE,NSW,-33.75,151.15,104.72.70.96 +DE,WEIMAR,HE,51.37,9.40,195.95.193.132 +IN,NAHAN,HP,30.55,77.30,2.21.240.61 +US,NASHOTAH,WI,43.1042,-88.4078,107.14.38.224 +IL,NIRIM,"",31.33,34.40,212.25.69.145 +US,LEXINGTONPARK,MD,38.2267,-76.4333,184.27.45.150 +US,WORTHINGTON,MN,43.6980,-95.6043,23.63.227.227 +IR,SEMNAN,"",35.58,53.39,80.239.149.123 +US,MECHANICSVILLE,VA,37.6340,-77.2585,23.79.240.36 +CZ,PRESTICE,"",49.57,13.32,23.62.237.137 +CA,SALABERRYDEVALLEYFIELD,QC,45.25,-74.13,67.69.197.92 +US,TOMSRIVER,NJ,39.9821,-74.1609,23.67.242.156 +US,EFFINGHAM,IL,39.1183,-88.6059,23.67.60.223 +US,ELKINSPARK,PA,40.0732,-75.1248,184.26.44.38 +US,NEWBRITAIN,CT,41.6612,-72.7801,184.25.109.200 +RO,DOROHOI,"",47.95,26.40,88.221.93.150 +US,UKIAH,CA,39.1539,-123.258,23.212.52.93 +US,ELMIRA,NY,42.1046,-76.758,107.14.38.218 +US,MEBANE,NC,36.1105,-79.2671,209.170.113.124 +US,CANTONMENT,FL,30.6195,-87.3241,96.17.153.162 +RO,DEJ,"",47.15,23.87,88.221.93.150 +PH,NAGA,"",12.53,122.10,80.239.237.230 +DE,LUDWIGSBURG,BW,48.90,9.18,84.53.175.90 +US,LOGANTON,PA,41.0290,-77.3175,165.254.35.197 +JP,TOYAMA,16,36.68,137.22,65.116.149.102 +US,COCHRAN,GA,32.4223,-83.3103,23.79.240.36 +US,GOTHENBURG,NE,40.9862,-100.1215,184.85.215.165 +PL,DABROWAGORNICZA,"",50.33,19.20,2.22.52.101 +DE,WALLDORF,HE,50.00,8.58,23.14.94.228 +US,PONCACITY,OK,36.7012,-97.1444,184.28.23.24 +CZ,USTINADORLICI,"",49.98,16.40,23.62.237.133 +US,SEBRING,FL,27.5025,-81.4505,184.51.207.83 +JP,IWAMIZAWA,01,43.20,141.77,23.3.74.113 +US,LEMARS,IA,42.8179,-96.1854,65.113.249.11 +US,KOSCIUSKO,MS,33.0153,-89.5142,165.254.138.175 +ID,SLEMAN,"",-6.47,108.30,23.0.162.21 +PH,CLARK,"",15.21,120.58,23.76.205.90 +US,MARLBOROUGH,MA,42.3495,-71.5482,23.220.148.122 +BR,CAXIASDOSUL,RS,-29.17,-51.18,177.159.174.7 +US,COMMERCECITY,CO,39.8641,-104.8219,184.84.180.98 +PL,WOJCIECH,"",53.87,23.08,2.22.52.105 +US,PLATTSMOUTH,NE,40.9697,-95.9883,184.85.215.165 +AT,HORN,"",48.65,15.65,195.145.147.108 +US,DUNN,NC,35.3234,-78.6207,24.143.197.207 +IT,AVELLINO,"",40.90,14.78,195.22.200.221 +US,FAIRPORT,NY,43.0902,-77.4171,107.14.38.217 +US,BLUEFIELD,VA,37.2441,-81.3675,209.48.37.183 +US,GULFBREEZE,FL,30.3906,-87.0518,96.17.153.157 +AU,BALLARAT,VIC,-37.57,143.85,202.7.177.87 +NL,PUTTE,"",51.37,4.38,92.122.189.85 +PL,IZABELA,"",52.20,21.30,23.14.94.224 +DE,EISENBERG,TH,50.97,11.90,92.122.207.164 +US,VINITA,OK,36.6347,-95.0928,23.212.53.75 +US,MOHEGANLAKE,NY,41.3106,-73.8477,184.26.44.38 +JP,KUNITACHI,13,35.68,139.44,96.7.251.95 +CA,PICKERING,ON,43.87,-79.03,72.246.43.215 +US,FORTATKINSON,WI,42.8930,-88.808,165.254.207.111 +US,GREENBRIER,TN,36.4312,-86.8077,23.79.240.37 +EE,NARVA,"",59.38,28.19,217.212.227.25 +PG,PORTMORESBY,"",-9.48,147.18,23.62.157.31 +US,HEREFORD,TX,34.9614,-102.6133,96.16.7.120 +US,EMPORIA,KS,38.5525,-96.1732,23.215.15.32 +RO,CORABIA,"",43.78,24.50,2.22.52.102 +ZA,WYNBERG,"",-26.10,28.08,95.101.2.113 +US,EASTHAMPTON,NY,40.9893,-72.1859,184.26.44.38 +SK,PIESTANY,"",48.60,17.83,23.14.94.224 +BF,OUAGADOUGOU,"",12.37,-1.52,184.27.45.157 +GB,FARNBOROUGH,EN,51.27,-0.73,184.27.45.150 +US,EXCELSIORSPRINGS,MO,39.3039,-94.2206,23.67.60.223 +DZ,BECHAR,"",31.62,-2.22,90.84.53.194 +ES,VALDECILLA,"",43.38,-3.73,2.20.44.111 +US,MANITOWOC,WI,44.0987,-87.7276,184.28.17.55 +AU,THORNLEIGH,NSW,-33.73,151.08,23.62.8.25 +US,OJAI,CA,34.5795,-119.1248,184.50.26.201 +AT,SIEZENHEIM,"",47.80,12.98,46.33.70.104 +AR,ALBERTI,"",-35.03,-60.27,200.123.201.219 +US,HIAWATHA,IA,42.0568,-91.6844,23.63.227.227 +PL,RODOWO,"",53.47,20.30,2.22.52.109 +DZ,CHLEF,"",36.16,1.33,90.84.53.224 +US,NEWPHILADELPHIA,OH,40.5013,-81.3604,107.14.38.217 +US,GASCITY,IN,40.4885,-85.6017,184.27.45.157 +DE,BRANDERBISDORF,SN,50.87,13.33,92.122.207.164 +RE,SAINTPIERRE,"",-21.32,55.48,23.15.10.106 +US,POLSON,MT,47.7086,-114.2472,23.212.53.64 +US,GRIFFIN,GA,33.2865,-84.3197,72.246.247.30 +US,SODASPRINGS,ID,42.7567,-111.4702,173.223.52.70 +US,ALPENA,MI,45.1042,-83.4937,23.74.8.24 +FI,PIETARSAARI,"",63.65,22.68,193.184.164.238 +US,HAZELWOOD,MO,38.7849,-90.3852,204.93.47.216 +BR,CAMPOGRANDE,MS,-20.45,-54.62,189.72.175.117 +US,KINGSVILLE,TX,27.4762,-97.7965,107.14.43.29 +US,LAVERNIA,TX,29.3560,-98.0927,23.215.15.22 +NO,KOLBOTN,"",59.81,10.80,2.21.240.40 +US,GRAYLING,MI,44.6717,-84.6485,23.79.255.153 +IL,RAMATGAN,"",32.08,34.81,2.18.243.1 +PH,BALABAG,"",11.98,121.92,184.84.239.186 +US,VERNONROCKVILLE,CT,41.8370,-72.4608,184.25.109.213 +US,GRANITEVILLE,SC,33.5725,-81.8284,204.2.243.132 +RU,TULA,"",54.20,37.61,80.239.217.231 +US,OKANOGAN,WA,48.3263,-119.6832,184.27.179.159 +US,TOWNSEND,TN,35.6244,-83.7794,23.79.240.37 +SE,UMEA,AC,63.83,20.25,2.21.240.40 +US,DERIDDER,LA,30.7742,-93.2493,23.5.164.143 +RU,KURGAN,"",53.71,37.10,2.22.52.105 +CH,LOCARNO,"",46.17,8.80,193.247.167.214 +US,GATLINBURG,TN,35.6579,-83.52,23.79.240.36 +US,ELLENWOOD,GA,33.6382,-84.2654,72.246.247.5 +CZ,CHOCEN,"",50.00,16.23,23.62.237.133 +IT,VICENZA,"",45.55,11.55,193.45.15.198 +CZ,CHOMUTOV,"",50.45,13.43,23.62.237.137 +US,ATOKA,TN,35.4184,-89.8065,184.51.147.33 +US,HAZLETON,PA,40.9531,-76.0034,165.254.48.154 +IN,ANDHERI,MH,19.12,72.83,23.211.135.66 +NZ,ROTORUA,"",-38.13,176.25,219.88.186.165 +US,CHIEFLAND,FL,29.4076,-82.903,184.51.145.7 +IR,RAMIN,"",35.58,51.06,165.254.48.155 +ZA,BRYANSTON,"",-26.05,28.03,41.193.163.53 +US,YADKINVILLE,NC,36.1267,-80.6582,184.51.35.226 +IN,RAMACHANDRAPURAM,AP,16.85,82.02,117.239.240.96 +CN,LISHUI,ZJ,28.45,119.90,204.2.166.220 +US,JAMAICAPLAIN,MA,42.3076,-71.1131,23.192.161.30 +US,WHITELAND,IN,39.5510,-86.0995,23.63.227.214 +US,NIAGARAFALLS,NY,43.0967,-79.0337,65.113.249.8 +DE,BADLAER,NI,52.10,8.08,92.122.207.164 +US,HORSHAM,PA,40.1879,-75.1531,23.67.242.139 +MY,BANDAR,"",2.87,101.43,23.198.99.130 +US,PINECITY,MN,45.8356,-92.9649,107.14.38.217 +RU,SARANSK,"",54.18,45.18,2.21.240.61 +US,KINGSBURG,CA,36.4785,-119.5245,96.17.12.44 +US,CATOOSA,OK,36.1721,-95.6946,23.5.164.143 +US,SPEARFISH,SD,44.4638,-103.897,107.14.38.227 +BD,CHITTAGONG,"",22.33,91.83,203.106.85.4 +KR,HWAGOK,"",37.42,127.73,61.111.58.229 +CH,FRAUENFELD,"",47.55,8.90,23.14.94.224 +US,BELMONT,NC,35.2342,-81.041,209.18.41.23 +AU,CAMBERWELL,VIC,-37.83,145.07,104.72.70.96 +CH,NIDAU,"",47.12,7.23,63.216.54.236 +US,KENDALLVILLE,IN,41.4608,-85.2531,65.113.249.11 +DE,SACHSEN,BY,49.30,10.40,213.200.109.183 +NZ,CROMWELL,"",-45.04,169.20,219.88.186.172 +US,CALEDONIA,MI,42.7912,-85.5517,23.63.227.214 +US,FISHKILL,NY,41.5306,-73.8899,184.51.125.79 +BY,NOVOPOLOTSK,"",55.53,28.65,217.212.227.25 +FR,ALLEVARD,"",45.40,6.07,2.16.117.200 +CN,XINYI,GD,22.35,110.94,216.206.101.214 +US,ASTORIA,NY,40.7715,-73.926,184.29.107.20 +US,SUSSEX,WI,43.1492,-88.2347,107.14.38.217 +CN,DONGGUAN,GD,23.03,113.73,184.50.87.178 +DE,NAILA,BY,50.32,11.70,23.14.94.224 +US,COCKEYSVILLE,MD,39.4879,-76.6611,23.67.242.156 +TL,DILI,"",-8.56,125.57,23.0.162.46 +GB,GRIMSBY,EN,53.53,-0.05,88.221.87.94 +PH,OLONGAPO,"",14.83,120.28,120.28.5.112 +US,ETNA,CA,41.4264,-123.0415,23.61.195.160 +US,NORTHAUGUSTA,SC,33.4766,-81.8963,23.79.240.36 +IN,MYSORE,KA,12.31,76.65,23.57.69.159 +US,MARCOISLAND,FL,25.9350,-81.6996,23.79.240.37 +US,HOMOSASSASPRINGS,FL,28.8033,-82.5763,23.33.186.134 +ID,AGUNG,"",-2.03,115.48,23.0.162.54 +PH,CUBAO,"",14.62,121.05,58.71.107.116 +US,BETHALTO,IL,38.9045,-90.0089,23.63.227.214 +PH,TAGUIG,"",14.54,121.06,58.71.107.120 +LV,JELGAVA,"",56.65,23.70,80.239.149.123 +RS,AVALA,"",44.43,19.93,2.20.45.104 +KE,KISUMU,"",-0.10,34.75,41.193.163.53 +US,DUMAS,TX,35.8084,-101.9581,23.215.15.22 +FR,MASSY,"",48.73,2.28,2.16.117.190 +US,CONNEAUTLAKE,PA,41.6180,-80.3248,209.48.37.183 +UA,YALTA,CRIMEA,44.50,34.17,23.14.94.224 +US,NEWBERN,NC,35.1731,-76.9871,184.28.17.76 +US,CARMICHAEL,CA,38.6263,-121.3281,184.84.180.68 +DE,KIRCHHEIMBOLANDEN,RP,49.67,8.02,23.14.94.220 +CA,POINTECLAIRE,QC,45.43,-73.75,165.254.35.197 +US,LURAY,VA,38.6496,-78.431,184.29.107.38 +US,ADELANTO,CA,34.6701,-117.539,184.50.26.194 +HR,RIJEKA,"",45.33,15.61,46.33.70.104 +RU,NEFTEYUGANSK,"",61.08,72.70,80.239.237.80 +US,BLACKMOUNTAIN,NC,35.5991,-82.3046,23.79.240.37 +US,NAPOLEONVILLE,LA,29.9154,-91.0326,23.79.240.37 +MX,SAHUAYODEMORELOS,MIC,20.07,-102.72,23.215.15.22 +US,SPRINGBRANCH,TX,29.8719,-98.3904,23.5.164.146 +JP,FUKUI,18,36.07,136.22,65.116.149.89 +US,PORTANGELES,WA,48.0203,-123.478,67.131.104.14 +CA,CLARKSON,ON,43.52,-79.62,72.246.43.215 +US,CAMBRIAHEIGHTS,NY,40.6944,-73.7359,23.215.15.9 +US,WEARE,NH,43.0801,-71.7237,184.29.107.38 +US,AIRWAYHEIGHTS,WA,47.6581,-117.5937,67.131.104.6 +IN,VALSAD,GJ,20.63,72.93,23.211.135.66 +RS,INDJIJA,"",45.05,20.08,23.62.237.133 +US,EASTLAND,TX,32.4120,-98.7997,23.212.53.75 +US,CORBIN,KY,36.9167,-84.1011,23.220.100.223 +US,MORTON,IL,40.6150,-89.4441,184.27.120.65 +DE,ROSENHEIM,BY,47.85,12.13,23.74.24.69 +HU,KAZINCBARCIKA,"",48.25,20.63,80.239.222.169 +FR,MONTREUIL,"",48.87,2.43,2.16.117.190 +US,FALFURRIAS,TX,27.2181,-98.2459,23.215.15.9 +US,HERMISTON,OR,45.8456,-119.2817,67.131.104.6 +US,WINNSBORO,SC,34.4133,-81.1456,204.2.243.143 +BR,MANAUS,AM,-3.11,-60.03,200.174.107.50 +DE,RASTATT,BW,48.85,8.20,2.16.217.206 +US,NORTHLIBERTY,IA,41.7609,-91.6574,96.17.9.8 +US,BROOKSHIRE,TX,29.8217,-95.9894,64.86.135.210 +US,AMBLER,PA,40.1823,-75.2133,184.26.44.40 +DE,GAGGENAU,BW,48.80,8.33,23.14.94.228 +US,CANYON,TX,34.8890,-101.9043,204.2.223.90 +US,ARDEN,NC,35.4582,-82.5975,96.16.12.216 +MV,NAIFARU,"",5.43,73.33,23.75.23.135 +FR,FERRIERESENGATINAIS,"",48.08,2.78,2.16.117.190 +US,CARROLL,IA,42.0800,-94.8598,65.113.249.8 +US,ALLEGAN,MI,42.5755,-85.8473,23.63.227.223 +US,CAMPBELL,CA,37.2798,-121.955,96.17.12.44 +BR,LONDRINA,PR,-23.30,-51.15,92.122.188.161 +SI,LOZ,"",45.73,14.48,2.20.142.166 +IN,MAHALAKSHMI,MH,18.98,72.80,23.57.69.157 +US,TUSCUMBIA,AL,34.6544,-87.6611,72.246.247.5 +AR,LANUS,"",-34.72,-58.41,200.123.201.215 +IN,MADHAPUR,AP,17.44,78.39,96.17.180.166 +AU,INDIGO,VIC,-36.10,146.57,104.72.70.95 +DE,LIPPE,NW,50.72,8.05,194.25.95.212 +US,ELKVIEW,WV,38.4976,-81.4683,184.28.17.76 +CH,CHIASSO,"",45.83,9.03,193.247.167.214 +US,ALVA,OK,36.8367,-98.8022,184.51.35.226 +US,AMERICANCANYON,CA,38.1778,-122.2572,23.212.52.82 +US,QUARTZSITE,AZ,33.6715,-114.2178,23.74.8.8 +AU,SURRYHILLS,NSW,-33.89,151.21,210.11.142.67 +DE,WEINGARTEN,RP,49.26,8.29,77.67.27.235 +PH,LOYOLA,"",8.33,126.33,23.76.205.111 +SK,NITRA,"",48.32,18.08,23.62.237.138 +US,SPRINGBORO,OH,39.5611,-84.22,107.14.38.224 +US,NORTHVERNON,IN,38.9859,-85.6189,23.74.8.8 +MY,KUCHING,"",1.55,110.33,203.106.85.4 +UA,IRSHAVA,"",48.32,23.05,2.22.52.102 +US,CORNELIA,GA,34.5117,-83.5924,184.25.157.169 +FR,LAGARDERE,"",43.83,0.32,90.84.50.108 +US,EBENSBURG,PA,40.4747,-78.7176,23.192.161.16 +KR,SUYUDONG,"",38.25,127.45,92.122.215.89 +AR,GUALEGUAYCHU,"",-33.01,-58.51,190.98.167.230 +HU,MONOR,"",47.35,19.45,88.221.93.150 +IR,ALI,"",31.88,50.00,96.17.182.130 +FR,LEHAVRE,"",49.50,0.13,2.16.117.200 +CA,TRURO,NS,45.37,-63.30,184.29.107.38 +CA,SAINTEFOY,QC,46.78,-71.30,72.246.43.233 +US,HIGHLANDPARK,NJ,40.5001,-74.4284,184.26.44.40 +GB,POPLAR,EN,51.50,-0.02,88.221.87.112 +US,WALKERSVILLE,MD,39.4904,-77.3477,23.192.161.21 +US,DAPHNE,AL,30.6100,-87.861,96.17.153.162 +FR,BOULOGNEBILLANCOURT,"",48.83,2.25,23.14.94.220 +RU,GEORGIEVSK,"",44.15,43.47,92.122.188.161 +PT,AMADORA,"",38.75,-9.23,212.113.165.116 +DE,AMBERG,BY,49.44,11.86,77.67.27.250 +DE,MARKKLEEBERG,SN,51.28,12.40,195.95.193.150 +DE,SANKTINGBERT,SL,49.28,7.12,194.25.95.212 +US,SPOTSYLVANIA,VA,38.1929,-77.6865,23.192.161.21 +CW,WILLEMSTAD,"",12.10,-68.92,72.246.65.26 +SA,DAMMAM,"",26.43,50.11,23.215.60.48 +MY,GENTING,"",5.28,100.38,58.26.185.116 +CO,IBAGUE,"",4.44,-75.23,200.14.44.100 +CA,NEPEAN,ON,45.45,-75.70,72.246.43.237 +DK,ODENSE,"",55.40,10.38,23.65.29.106 +JP,SANO,09,36.32,139.58,23.3.104.29 +FR,FONTENAYSOUSBOIS,"",48.85,2.48,88.221.15.110 +TR,BILGI,"",38.10,43.25,193.45.15.198 +DM,ROSEAU,"",15.30,-61.40,23.74.2.7 +US,COFFEYVILLE,KS,37.0670,-95.5817,23.215.15.32 +US,PALMYRA,VA,37.8582,-78.2803,184.26.44.40 +CZ,CESKALIPA,"",50.68,14.55,23.62.237.133 +US,ROXBORO,NC,36.4264,-78.951,23.79.240.48 +ID,GEDONG,"",-6.22,106.90,23.0.162.46 +US,GEYSERVILLE,CA,38.7422,-122.8612,184.84.180.92 +PL,SZCZECINEK,"",53.72,16.70,80.239.222.190 +US,SUFFERN,NY,41.1483,-74.1189,23.67.242.156 +FR,PAU,"",43.30,-0.37,2.16.117.190 +DE,HOHENHEIM,BW,48.70,9.22,2.20.142.173 +US,EUSTIS,FL,28.8842,-81.4638,23.79.240.48 +US,STEILACOOM,WA,47.1696,-122.5937,23.212.59.85 +US,RIFLE,CO,39.7934,-108.1357,184.84.180.68 +US,BROADVIEW,IL,41.8498,-87.8859,23.67.60.220 +US,BEATRICE,NE,40.2674,-96.7699,165.254.207.111 +US,WINNEMUCCA,NV,41.1353,-118.1862,65.113.249.11 +CN,QINHUANGDAO,HE,39.93,119.59,23.76.205.90 +US,CHINOVALLEY,AZ,34.8245,-112.4595,63.226.34.176 +US,WESTBEND,WI,43.4212,-88.1854,65.113.249.8 +UA,KRASNOARMEYSK,"",47.15,31.03,92.122.215.89 +US,CENTRALCITY,KY,37.3137,-87.1024,23.79.240.36 +FR,PORTDEBOUC,"",43.40,4.98,2.16.117.190 +US,PEARLCITY,HI,21.4205,-157.9279,184.50.26.203 +FR,PERTUIS,"",43.68,5.50,2.16.117.200 +AT,MITTERRETZBACH,"",48.79,15.99,195.145.147.109 +ZA,RANDBURG,"",-26.10,27.98,41.193.163.53 +US,KENNETT,MO,36.2279,-90.0425,96.17.14.16 +US,HOSCHTON,GA,34.0890,-83.7695,63.216.54.231 +BG,TARNOVO,"",43.07,25.65,23.14.94.220 +US,PARKVILLE,MD,39.3955,-76.5329,23.67.242.156 +US,INMAN,SC,35.0511,-82.0561,63.216.54.231 +US,STROUDSBURG,PA,40.9882,-75.2974,23.67.242.156 +HU,BOLY,"",45.97,18.52,81.93.191.127 +US,NORTHVILLE,MI,42.4188,-83.5284,23.67.60.220 +FI,LAPPEENRANTA,"",61.07,28.18,2.21.240.40 +PL,GDYNIA,"",54.50,18.55,2.22.52.105 +US,SHELLEY,ID,43.2015,-111.522,206.104.149.146 +FR,BERSEE,"",50.48,3.15,2.16.117.200 +US,HOOPESTON,IL,40.4428,-87.6416,23.74.8.8 +US,PLOVER,WI,44.4117,-89.5378,184.85.215.170 +US,MONTVERNON,NH,42.9030,-71.6963,184.25.109.201 +CA,SIOUXLOOKOUT,ON,50.10,-91.92,72.246.43.232 +NE,NIAMEY,"",13.52,2.12,81.52.201.98 +RU,STROITELEY,"",56.25,43.40,80.239.217.238 +US,MICCOSUKEE,FL,30.5947,-84.0417,23.79.240.36 +FR,LEPECQ,"",48.90,2.10,2.16.117.200 +US,NORTHEASTON,MA,42.0558,-71.1216,23.62.238.220 +CN,ZHOUSHAN,ZJ,30.02,122.10,23.15.10.91 +US,JEFFERSONVILLE,IN,38.3363,-85.6984,23.220.100.223 +AT,PRIEL,"",48.45,15.57,88.221.93.150 +RU,MIR,"",58.45,39.42,2.21.240.40 +JP,KYODO,13,35.67,139.75,72.246.184.81 +US,CARRIZOSPRINGS,TX,28.4732,-99.976,96.17.163.161 +SO,HARGEISA,"",9.58,44.07,95.101.34.109 +US,FRANKENMUTH,MI,43.3550,-83.7419,184.51.35.215 +PT,EVORA,"",39.52,-8.97,195.22.14.134 +US,DOWNINGTOWN,PA,40.0250,-75.7202,23.67.242.156 +FR,DOMONT,"",49.03,2.33,2.16.117.190 +US,OAKMAN,AL,33.6727,-87.3688,184.51.35.226 +US,JENNINGS,LA,30.1991,-92.6684,23.79.240.36 +PR,BAYAMON,"",18.4008,-66.1589,192.204.82.221 +DE,NEIDLINGEN,BY,49.22,10.32,80.157.170.154 +CH,KAISERAUGST,"",47.53,7.72,193.247.167.214 +BR,OSASCO,SP,-23.57,-46.78,200.174.107.50 +FI,KUUSAMO,"",65.97,29.18,2.21.240.40 +US,BISHOP,CA,37.4772,-118.401,63.151.119.25 +US,BELLS,TX,33.6182,-96.434,23.5.164.146 +US,PARRISH,FL,27.5583,-82.2583,165.254.205.13 +DE,ZANDT,BY,49.23,10.65,195.145.147.108 +US,GARNETT,KS,38.2898,-95.2918,209.170.117.178 +US,STATHAM,GA,33.9449,-83.5889,72.246.247.5 +IR,BIRJAND,"",32.89,59.24,80.239.222.167 +US,PEARISBURG,VA,37.2475,-80.7675,184.27.45.157 +AU,RYDE,NSW,-33.82,151.10,202.7.177.87 +RO,MORENI,"",44.98,25.65,88.221.93.150 +JP,OTSU,25,35.00,135.87,117.104.139.136 +RU,SYZRAN,"",53.17,48.47,80.239.237.93 +MA,MARRAKECH,"",31.63,-8.00,2.20.44.111 +US,FUQUAYVARINA,NC,35.5406,-78.8329,209.18.41.27 +US,HOOPER,UT,41.1783,-112.1209,23.61.195.150 +US,MINERSVILLE,PA,40.6888,-76.2602,23.192.161.16 +FR,COURNONDAUVERGNE,"",45.75,3.22,2.16.117.200 +US,HATFIELD,PA,40.2766,-75.2964,23.67.242.156 +NL,WOERDEN,"",52.08,4.92,92.122.189.114 +US,ENID,OK,36.3867,-97.8158,23.5.164.143 +US,CARNEGIE,PA,40.4095,-80.1154,184.27.45.150 +NG,IBADAN,"",6.53,2.77,23.212.108.8 +FI,HAMEENLINNA,"",61.00,24.45,213.155.156.212 +BA,BANJALUKA,"",44.78,17.19,80.239.237.230 +GE,BOLNISI,"",41.45,44.54,92.122.215.67 +US,STUART,FL,27.1804,-80.2454,23.79.240.36 +CH,ARLESHEIM,"",47.48,7.62,23.14.94.214 +AT,LANDECK,"",47.13,10.57,46.33.70.97 +CZ,JICINA,"",49.57,17.97,2.20.142.173 +US,SELMER,TN,35.1420,-88.6514,23.79.240.36 +US,ORANGEPARK,FL,30.1070,-81.7167,23.79.240.36 +US,LANGHORNE,PA,40.1816,-74.9144,184.26.44.38 +IT,BRESCIA,"",45.55,10.25,95.101.34.109 +CA,MOUNTPEARL,NF,47.52,-52.78,67.69.197.95 +HK,TSUENWAN,"",22.37,114.10,23.76.205.90 +MY,LIKAS,"",5.98,116.10,96.17.180.177 +KZ,KYZYLORDA,"",44.85,65.51,217.212.227.25 +US,ONLEY,VA,37.6704,-75.7049,184.27.45.157 +RO,PASCANI,"",44.63,26.20,77.67.27.250 +CH,PREGASSONA,"",46.03,8.97,193.45.15.199 +RU,ALEXANDROV,"",56.40,38.72,2.21.240.61 +US,GRANTS,NM,35.2644,-107.7333,63.151.29.15 +US,BATTLEBORO,NC,35.8571,-77.4097,63.151.29.12 +FI,TAIVALKOSKI,"",65.57,28.25,2.21.240.61 +SK,ZILINA,"",49.22,18.73,23.14.94.214 +PL,ZORY,"",50.05,18.70,2.22.52.109 +NL,VAASSEN,"",52.28,5.97,92.122.189.114 +NO,SOGN,"",60.30,10.42,213.155.156.206 +US,OGDENSBURG,NY,44.7176,-75.3859,184.29.107.20 +AF,BAGRAM,"",34.95,69.25,2.22.52.102 +US,PALOSHEIGHTS,IL,41.6608,-87.7892,23.67.60.223 +US,GRUNDYCENTER,IA,42.3726,-92.793,23.63.227.227 +DZ,ORAN,"",35.69,-0.64,90.84.53.225 +RO,PIATRANEAMT,"",46.92,26.33,80.239.222.169 +US,BLOUNTSTOWN,FL,30.3988,-85.0821,204.2.243.132 +US,KINGGEORGE,VA,38.2650,-77.1228,208.185.55.86 +US,DIXON,IA,41.7085,-90.7516,65.113.249.11 +US,ELKRIVER,MN,45.3450,-93.5658,63.151.29.15 +JO,IRBID,"",32.56,35.85,77.67.27.235 +US,FORTRILEY,KS,38.9760,-96.6098,204.94.155.231 +US,COLDWATER,MI,41.9063,-85.0231,23.79.255.153 +US,ALICE,TX,27.6821,-98.1034,23.5.164.143 +US,HELOTES,TX,29.6143,-98.747,96.17.163.161 +US,ATMORE,AL,31.1324,-87.4695,96.6.47.106 +CA,NIAGARAONTHELAKE,ON,43.25,-79.07,72.246.43.215 +US,DELPHOS,OH,40.8243,-84.3284,23.74.8.8 +US,OKMULGEE,OK,35.6454,-96.0285,165.254.138.175 +FR,ARS,"",49.08,6.07,23.200.87.58 +AT,KATSDORF,"",48.32,14.47,195.145.147.109 +US,MIDDLEFIELD,OH,41.4619,-81.025,63.216.54.229 +SE,HACKSTA,AB,59.48,18.30,2.21.240.61 +US,SOUTHORANGE,NJ,40.7490,-74.2606,23.62.238.220 +FR,GRASSE,"",43.67,6.92,2.16.117.190 +US,AIKEN,SC,33.6484,-81.682,204.2.243.64 +SK,TOPOLCANY,"",48.57,18.18,23.62.237.133 +ZW,BULAWAYO,"",-20.15,28.58,41.193.163.45 +US,CULPEPER,VA,38.4670,-77.9818,23.67.242.139 +CN,JINCHENG,SX,35.50,112.83,72.246.191.19 +DE,BURGDORF,NI,52.15,10.22,80.157.170.154 +US,OLIN,IA,41.9909,-91.1308,65.113.249.8 +RU,ZVEZDA,"",54.11,36.78,92.122.188.163 +DE,OBERURSEL,HE,50.20,8.58,92.122.215.89 +US,FAIRPLAY,CO,39.1352,-105.9815,23.212.53.75 +IL,MIGDAL,"",32.83,35.50,212.25.69.134 +FR,EGUILLES,"",43.57,5.37,2.16.117.190 +IR,NOVIN,"",35.19,46.36,23.57.76.18 +RU,KANSK,"",56.20,95.71,184.51.199.145 +IN,THIRUVANANTHAPURAM,KL,8.51,76.96,23.211.135.66 +NZ,INVERCARGILL,"",-46.40,168.35,219.88.186.164 +US,GUNNISON,CO,38.5539,-107.0907,184.50.26.179 +US,ATWATER,CA,37.2953,-120.6669,96.17.12.44 +US,NORTHBROOKFIELD,MA,42.2695,-72.0791,184.25.157.169 +US,HARWINTON,CT,41.7549,-73.0582,63.141.200.241 +US,PAYETTE,ID,44.0773,-116.6967,206.104.149.133 +US,THIEFRIVERFALLS,MN,48.0818,-96.1186,23.79.240.36 +PL,ZABRZE,"",50.32,18.78,213.200.109.173 +FR,LESPINASSE,"",44.98,1.03,2.16.117.190 +US,MOLINE,IL,41.4843,-90.4905,65.113.249.8 +RO,RASNOV,"",45.58,25.45,81.196.26.236 +US,SHARON,PA,41.2346,-80.4992,184.27.45.157 +US,HERSHEY,PA,40.2634,-76.626,23.67.242.139 +US,BROOKSVILLE,FL,28.5914,-82.358,23.33.186.101 +CA,SAINTHUBERT,QC,47.80,-69.15,67.69.197.92 +IL,DANIEL,"",31.93,34.93,212.25.69.145 +US,GORHAM,NH,44.3296,-71.1352,107.14.38.217 +US,WINTERVILLE,NC,35.5203,-77.4072,184.28.17.55 +KE,MOMBASA,"",-4.05,39.67,2.16.1.90 +TR,COM,"",36.07,36.25,193.45.15.198 +JP,TOHO,41,33.48,129.93,72.246.184.92 +US,FORTSILL,OK,34.6684,-98.399,23.5.164.143 +US,CORTEZ,CO,37.3484,-108.7341,64.129.104.135 +US,NEWCUMBERLAND,PA,40.2034,-76.87,184.26.44.40 +US,ONEALS,CA,37.1445,-119.6517,173.223.52.67 +FI,RAISIO,"",60.48,22.18,82.96.58.85 +TR,AYDIN,"",40.17,32.68,193.45.15.198 +DE,MONTABAUR,RP,50.43,7.83,77.67.27.235 +US,LINWOOD,KS,39.0229,-95.0014,209.170.117.169 +US,PORTALLEN,LA,30.4802,-91.3238,23.215.15.22 +RU,KOMSOMOLSK,"",57.03,40.38,2.21.240.61 +US,ELONCOLLEGE,NC,36.2189,-79.4807,23.215.15.22 +US,ATHERTON,CA,37.4538,-122.2033,23.212.52.82 +US,BRAY,OK,34.6379,-97.8173,23.215.15.22 +BR,ALFENAS,MG,-21.43,-45.95,200.216.8.55 +US,SCHERERVILLE,IN,41.4906,-87.4618,107.14.38.224 +US,GURNEE,IL,42.3764,-87.9424,107.14.38.227 +US,GLOUCESTERCITY,NJ,39.8885,-75.1173,184.26.44.38 +CA,OAKVILLE,ON,43.43,-79.67,72.246.43.233 +US,DEMING,NM,32.1825,-107.7499,23.215.15.22 +PL,PABIANICE,"",51.67,19.37,80.239.222.167 +BR,POUSOALEGRE,MG,-22.22,-45.93,200.216.8.55 +TR,MUGLA,"",37.20,28.37,193.45.15.199 +US,BRYANT,AR,34.5942,-92.5003,184.28.127.55 +US,MINERALWELLS,TX,32.7965,-98.1108,23.5.164.143 +CZ,VRBNOPODPRADEDEM,"",50.12,17.38,23.62.237.135 +UZ,SAMARKAND,"",39.65,66.96,80.239.222.167 +US,SASSAMANSVILLE,PA,40.3419,-75.5728,184.26.44.38 +JP,TAMASHIMA,33,34.53,133.67,23.15.1.29 +PL,OLSZTYN,"",53.78,20.48,80.157.149.129 +US,CLAXTON,GA,32.1564,-81.8865,23.79.240.48 +US,NAHUNTA,GA,31.1753,-81.969,23.212.53.75 +US,CARRBORO,NC,35.9085,-79.0807,209.18.41.23 +AU,TOWNSVILLE,QLD,-19.25,146.80,202.7.177.76 +FR,VERNANTES,"",47.40,0.05,2.16.117.200 +US,GRANDRONDE,OR,45.1093,-123.6869,184.27.179.187 +JP,SANNO,08,35.93,140.07,23.15.1.29 +US,BAXTER,TN,36.1069,-85.6452,204.2.243.143 +CA,SACKVILLE,NB,45.88,-64.35,184.29.107.38 +RU,SYKTYVKAR,"",61.67,50.81,80.239.237.231 +DE,COBURG,BY,50.25,10.97,92.122.215.89 +CZ,HORICE,"",49.60,15.18,23.62.237.133 +US,CHESTERTON,IN,41.6139,-87.0454,23.67.60.222 +US,DENVERCITY,TX,33.0189,-102.7913,65.113.249.11 +US,KNOX,IN,41.2954,-86.6039,65.113.249.8 +US,KYLE,TX,29.9978,-97.835,23.215.15.22 +FR,CHEVIGNYSAINTSAUVEUR,"",47.30,5.13,2.16.117.200 +AT,KREMSANDERDONAU,"",48.42,15.60,195.145.147.108 +DE,KURZ,BY,47.62,12.17,23.14.94.224 +US,BELGIUM,WI,43.4979,-87.8642,107.14.38.217 +US,SHOREHAM,VT,43.8808,-73.3057,165.254.48.150 +US,BASKINGRIDGE,NJ,40.6763,-74.5643,209.170.113.124 +UA,UZHGOROD,"",48.62,22.30,2.22.52.102 +RU,PERVOURALSK,"",56.91,59.95,2.21.240.40 +RU,PLASTUN,"",44.76,136.29,96.7.251.95 +WF,MATAUTU,"",-13.28,-176.13,104.72.70.96 +US,MINEOLA,TX,32.6629,-95.4808,23.5.164.146 +US,MOSSPOINT,MS,30.4116,-88.5345,24.143.197.207 +US,GREENWICH,CT,41.0502,-73.6235,184.26.44.38 +US,ANNAPOLIS,MD,38.9918,-76.5525,23.192.161.30 +CN,XUANWU,HA,33.97,115.23,23.2.16.103 +US,MEQUON,WI,43.2406,-88.022,23.63.227.214 +HU,PESTSZENTLORINC,"",47.43,19.20,23.14.94.224 +US,INKSTER,MI,42.2932,-83.3147,23.67.60.223 +DE,BERENBERG,BW,47.90,9.03,23.14.94.214 +DE,BEVERUNGEN,NW,51.67,9.37,92.122.207.179 +CZ,HRANICE,"",49.75,14.25,23.62.237.133 +US,WOODRIDGE,IL,41.7537,-88.05,23.67.60.220 +PL,STARGARDSZCZECINSKI,"",53.33,15.05,80.239.222.167 +RS,MITROVIC,"",42.88,20.87,23.62.237.133 +US,MEDFIELD,MA,42.1847,-71.3048,184.25.109.213 +FR,CADEROUSSE,"",44.10,4.75,2.16.117.200 +RU,ZHUKOVSKIY,"",55.61,38.11,80.239.217.231 +US,WOODINVILLE,WA,47.7581,-122.094,23.212.59.85 +US,BRAZORIA,TX,28.9272,-95.5834,23.63.227.214 +US,ATCHISON,KS,39.5229,-95.1427,65.113.249.8 +AU,FINDON,SA,-34.90,138.53,23.205.117.14 +IT,CARRARA,"",44.08,10.10,193.45.15.198 +US,HOODRIVER,OR,45.5726,-121.6583,184.27.179.159 +US,MONTPELIER,VT,44.2601,-72.5759,184.25.109.200 +KW,AHMADI,"",29.08,48.08,23.212.108.8 +CN,JIEYANG,GD,23.55,116.33,107.14.44.212 +ZA,PORTELIZABETH,"",-33.97,25.58,41.193.163.53 +FR,MAXEVILLE,"",48.72,6.17,23.14.94.214 +FI,TAMPERE,"",61.50,23.75,82.96.58.85 +US,MONTAGUE,MA,42.5391,-72.5186,184.25.109.201 +IT,SANPAOLO,"",45.37,10.02,193.45.15.198 +US,FARMINGDALE,NY,40.7334,-73.4289,184.26.44.38 +US,TIJERAS,NM,34.9842,-106.3226,23.212.52.79 +US,GUTHRIE,OK,35.8319,-97.4802,23.215.15.32 +CH,ZUG,"",47.17,8.52,193.247.167.214 +US,APEX,NC,35.7358,-78.8955,96.16.12.216 +UA,MELNIK,"",49.32,25.27,23.14.94.224 +US,ODENVILLE,AL,33.6693,-86.4042,63.216.54.229 +US,MOUNTSHASTA,CA,41.3683,-122.2492,23.61.195.165 +US,COLLEGEDALE,TN,35.0534,-85.0503,184.51.35.215 +FR,GUYANCOURT,"",48.77,2.07,2.16.117.190 +HU,TISZAVASVARI,"",47.97,21.35,194.25.95.214 +US,MARTINEZ,CA,37.9788,-122.1647,23.212.52.82 +US,KEANSBURG,NJ,40.4416,-74.1294,23.67.242.156 +CZ,ZLIN,"",49.23,17.67,23.62.237.137 +DE,GOELLHEIM,RP,49.59,8.05,23.14.94.224 +US,MANGUM,OK,34.8485,-99.5641,96.16.7.101 +IN,KHAMMAM,AP,17.25,80.15,96.17.182.130 +SE,SODERHAMN,AB,59.45,18.58,107.14.32.235 +US,PARKRIDGE,IL,42.0122,-87.8435,107.14.38.224 +US,JENISON,MI,42.9189,-85.8361,65.113.249.11 +TR,ERDEM,"",37.30,40.62,77.67.27.250 +US,HAVERTOWN,PA,39.9771,-75.3116,23.67.242.156 +US,CHELMSFORD,MA,42.5915,-71.3555,23.62.238.215 +MX,CHIHUAHUA,CHH,28.63,-106.08,92.122.188.163 +US,BAYSHORE,NY,40.7379,-73.2632,184.26.44.40 +CN,XIAMEN,FJ,24.45,118.08,184.50.87.176 +US,NAUGATUCK,CT,41.4890,-73.0518,184.25.109.200 +US,WILLIAMS,AZ,35.6062,-112.4411,63.226.34.176 +US,HOBESOUND,FL,27.0409,-80.17,23.79.240.36 +TR,TRABZON,"",41.00,39.72,23.74.24.69 +US,NORTHPLATTE,NE,41.1392,-100.7774,184.85.215.170 +SK,RUZOMBEROK,"",49.08,19.32,23.62.237.133 +IN,GANDHINAGAR,GJ,23.22,72.68,23.211.135.110 +CN,CAOXIAN,SD,34.82,115.53,23.3.104.15 +US,BEARDSTOWN,IL,39.9762,-90.4107,23.63.227.214 +US,BENICIA,CA,38.1051,-122.1359,96.17.12.44 +PL,BIALA,"",51.80,20.48,2.22.52.105 +US,FORTLOUDON,PA,39.9814,-77.8809,23.192.161.30 +ID,DATA,"",-8.30,115.61,80.239.237.230 +US,BEAVERDAM,WI,43.4576,-88.8551,184.85.215.165 +US,MOUNTLAKETERRACE,WA,47.7924,-122.3065,23.212.59.63 +CA,OMPAH,ON,45.02,-76.83,209.148.192.61 +US,PENNINGTONGAP,VA,36.7557,-83.038,23.79.240.48 +US,IUKA,MS,34.8106,-88.1999,96.17.153.162 +BY,ORSHA,"",54.52,30.41,80.239.222.167 +US,TORRINGTON,WY,41.9687,-104.195,63.226.34.176 +IL,DAN,"",33.24,35.65,82.102.137.137 +US,BARRINGTON,IL,42.1512,-88.1636,107.14.38.217 +US,TEMPLETON,CA,35.5330,-120.6957,23.61.195.165 +US,SAULTSAINTEMARIE,MI,46.3629,-84.3293,23.63.227.214 +DE,MITTWEIDA,SN,50.53,12.87,2.20.142.173 +RU,DZERZHINSK,"",56.24,43.46,213.155.156.207 +US,PLEASANTVIEW,TN,36.3846,-87.0359,23.215.60.48 +US,PALISADESPARK,NJ,40.8468,-73.9958,24.143.199.188 +US,GEISMAR,LA,30.2217,-91.0044,23.215.15.9 +CN,DUYUN,GZ,26.27,107.52,72.246.191.19 +RU,NORILSK,"",69.33,88.10,217.212.227.25 +US,WAHOO,NE,41.2013,-96.6192,165.254.207.117 +US,RAYMONDVILLE,TX,26.5112,-97.8502,23.215.15.9 +AT,ERPFENDORF,"",47.58,12.47,195.145.147.101 +BG,YAMBOL,"",42.48,26.50,23.62.237.137 +US,FITCHBURG,MA,42.5924,-71.8176,184.26.44.38 +AT,PERCHTOLDSDORF,"",48.12,16.27,46.33.70.97 +RU,CHELNY,"",55.23,48.90,213.155.156.206 +IL,EINHAHORESH,"",32.38,34.93,82.102.137.137 +SE,VISBY,I,57.63,18.30,213.155.156.206 +IR,YAZD,"",31.90,54.37,77.67.96.114 +LT,GIEDRAICIU,"",55.08,25.28,2.21.240.61 +US,FAIRHOPE,AL,30.4849,-87.8614,96.17.153.162 +UA,RADIO,"",47.70,33.85,2.20.142.173 +CZ,ROUDNICENADLABEM,"",50.42,14.25,23.62.237.137 +PL,SOSNOWIEC,"",51.88,19.57,2.22.52.102 +AR,AVELLANEDA,"",-34.65,-58.38,200.123.201.219 +US,PLAINWELL,MI,42.4690,-85.5608,23.212.53.75 +US,TAHLEQUAH,OK,35.9078,-95.0047,23.215.15.9 +US,PENNSAUKEN,NJ,39.9750,-75.0476,184.26.44.38 +SE,EKSJO,F,57.67,14.95,217.212.227.25 +AT,GAUBITSCH,"",48.65,16.38,195.145.147.101 +US,WALDRON,AR,34.9204,-94.0577,209.170.117.178 +JP,NAGASAKI,42,32.80,129.92,23.3.104.29 +DZ,BEJAIA,"",36.75,5.08,92.122.189.85 +CA,ABBOTSFORD,BC,49.05,-122.30,24.244.17.205 +US,BARRE,VT,44.1738,-72.4252,72.247.10.237 +IT,SINOPOLI,"",38.27,15.88,95.101.34.109 +US,ANGWIN,CA,38.5873,-122.4459,23.61.195.163 +US,BUNKERHILL,WV,39.3176,-78.0485,184.27.45.157 +US,STRASBURG,CO,39.8693,-103.9998,184.28.23.4 +US,BYRONCENTER,MI,42.7984,-85.7381,23.67.60.222 +US,CUTBANK,MT,48.8080,-112.4878,107.14.32.235 +UA,TERNOPIL,"",49.55,25.58,2.22.52.102 +BJ,COTONOU,"",6.35,2.43,80.239.171.190 +AR,PARANA,"",-31.73,-60.53,200.123.201.219 +US,OAKHALL,VA,37.9340,-75.5755,184.25.157.162 +US,GRANTHAM,PA,40.1564,-76.9967,184.26.44.38 +US,CORINTH,MS,34.9238,-88.6234,184.27.45.157 +ER,ASMERA,"",15.33,38.93,82.102.137.137 +IN,ALWAR,RJ,27.57,76.60,96.17.182.130 +DE,STRASSE,NW,50.87,7.48,80.157.170.221 +FR,BRIVELAGAILLARDE,"",45.15,1.53,2.16.117.200 +SE,SOLBACKEN,AB,59.12,18.24,213.155.156.208 +US,AUSTINBURG,OH,41.7602,-80.8589,63.216.54.216 +CO,NARINO,"",4.40,-74.83,200.14.44.104 +CZ,PARDUBICE,"",50.03,15.78,88.221.93.157 +US,MANLIUS,NY,42.9680,-75.9513,107.14.38.227 +US,MASTICBEACH,NY,40.7682,-72.8409,184.26.44.40 +US,CHIPLEY,FL,30.6040,-85.5678,96.17.153.157 +US,COLEMAN,TX,31.8779,-99.43,173.197.194.159 +PL,SKOCZOW,"",49.80,18.80,2.22.52.101 +US,TEXARKANA,TX,33.3633,-94.2141,23.215.15.32 +DE,EDENKOBEN,RP,49.29,8.12,80.157.170.221 +PR,MOROVIS,"",18.3346,-66.4186,72.246.65.37 +US,MORRISON,CO,39.5990,-105.2281,23.63.227.214 +US,MERCERISLAND,WA,47.5624,-122.2266,23.212.59.85 +US,CONNELLSVILLE,PA,39.9618,-79.5876,209.48.37.183 +CN,YANGQUAN,SX,37.86,113.56,72.246.191.16 +TH,CHANG,"",18.85,100.82,203.144.145.96 +US,BROWNFIELD,TX,33.1115,-102.3365,63.216.54.216 +CZ,SUSICE,"",49.92,15.60,23.62.237.138 +CZ,PELHRIMOV,"",49.43,15.23,23.62.237.133 +US,RICHLANDS,VA,37.1242,-81.807,184.26.93.111 +JP,AKITA,05,39.72,140.07,96.7.251.95 +US,SIXES,OR,42.8041,-124.3226,63.217.232.17 +CZ,CERNOVICE,"",49.37,14.97,23.62.237.137 +AR,GENERALPICO,"",-35.67,-63.73,190.98.167.220 +RU,TATARSTAN,"",52.90,141.07,2.21.240.40 +US,EAGLE,ID,43.7768,-116.3919,184.27.179.187 +CN,CHANGDE,HN,29.03,111.68,117.104.139.162 +US,BONNERSFERRY,ID,48.8159,-116.6507,184.27.179.181 +US,ZEELAND,MI,42.8513,-85.9891,23.63.227.214 +DK,SKAARUP,"",54.70,11.67,23.65.29.106 +FR,SAINTGERMAINLESCORBEIL,"",48.62,2.48,2.16.117.190 +US,DARIEN,GA,31.4067,-81.499,204.2.243.132 +ES,REDES,"",43.42,-8.20,2.20.44.111 +US,CARRINGTON,ND,47.4573,-99.0752,23.79.255.149 +US,REEDCITY,MI,43.9034,-85.5104,23.63.227.227 +US,FOWLERVILLE,MI,42.6682,-84.0758,107.14.38.224 +FR,TRESSIN,"",50.60,3.20,2.16.117.200 +TH,MUANGRAJBURI,"",13.53,99.80,61.19.12.177 +RU,SUMMA,"",60.50,29.02,217.212.227.25 +US,MITCHELL,SD,43.7034,-98.0626,23.63.227.227 +CZ,JIHLAVA,"",49.40,15.58,23.62.237.137 +FR,EAUBONNE,"",49.00,2.28,2.16.117.200 +BG,BISTRICA,"",42.23,23.17,92.122.215.89 +US,UVALDE,TX,29.3417,-99.8887,107.14.36.199 +IN,DWARKA,GJ,22.24,68.97,2.21.240.40 +US,LITHIASPRINGS,GA,33.7656,-84.6415,23.79.240.48 +US,LENORA,KS,39.6800,-99.7571,23.77.234.35 +AU,POTTSPOINT,NSW,-33.87,151.22,23.62.8.25 +US,HAINES,AK,59.1202,-135.7004,24.244.17.205 +NO,KVITESEID,"",59.40,8.50,213.155.156.206 +BD,COMILLA,"",23.45,91.20,23.57.76.18 +US,RICHFIELD,UT,38.7083,-111.7291,23.61.195.163 +GB,GATWICK,EN,51.17,-0.18,23.212.108.8 +US,LILLINGTON,NC,35.3213,-78.9874,184.28.127.58 +US,GREENACRES,WA,47.6286,-117.1038,206.104.149.146 +US,GRANTSVILLE,MD,39.6703,-79.1506,184.26.44.38 +CZ,RAKOVNIK,"",50.10,13.75,23.62.237.137 +US,PETAL,MS,31.3432,-89.178,96.17.153.162 +CZ,MNICHOVICE,"",49.93,14.70,23.62.237.137 +US,HOHENWALD,TN,35.5255,-87.548,23.79.240.36 +US,PECULIAR,MO,38.7126,-94.4101,23.212.53.75 +CN,YIGAO,ZJ,30.93,120.29,72.246.191.19 +CN,JILIN,JL,43.86,126.57,184.51.199.132 +IN,UDHAMPUR,JK,32.93,75.13,117.239.91.75 +PL,OBORNIKISLASKIE,"",51.30,16.92,2.22.61.102 +US,HEDGESVILLE,WV,39.5195,-78.0934,23.192.161.30 +FR,LEOGNAN,"",44.73,-0.60,2.16.117.190 +RO,GHEBOAIA,"",44.80,25.75,2.22.52.109 +US,WILLCOX,AZ,32.5598,-110.08,63.226.34.172 +DE,SANDESNEBEN,SH,53.68,10.50,92.122.207.179 +FR,AVALLON,"",47.48,3.90,2.16.117.200 +US,HAVREDEGRACE,MD,39.5690,-76.1506,165.254.48.142 +IL,ASHDOD,"",31.82,34.65,212.25.69.142 +KE,NAKURU,"",-0.28,36.07,2.16.1.106 +US,TRUCKEE,CA,39.3282,-120.1822,23.5.164.143 +US,MARIANNA,FL,30.7390,-85.2383,23.79.240.36 +UA,MARIUPOL,"",47.10,37.55,80.239.237.230 +RO,CAREI,"",47.68,22.47,81.196.26.231 +US,WESTFRANKFORT,IL,37.9074,-88.9501,165.254.207.117 +HU,TEGLAS,"",47.72,21.68,23.14.94.228 +NL,SHERTOGENBOSCH,"",51.70,5.32,2.16.153.173 +US,LINCOLNWOOD,IL,42.0082,-87.731,23.67.60.223 +US,BROADVIEWHEIGHTS,OH,41.3194,-81.6781,96.17.9.8 +US,GALESBURG,IL,40.9508,-90.3832,65.113.249.11 +PL,KUZNIARACIBORSKA,"",50.20,18.30,213.200.109.183 +US,GIBSONIA,PA,40.6378,-79.9434,209.48.37.188 +AU,MONASH,SA,-34.23,140.57,104.72.70.96 +CA,BANFF,AB,51.17,-115.57,24.244.17.205 +IR,PASARGAD,"",30.20,53.18,23.14.94.214 +US,INWOOD,WV,39.3765,-78.0298,23.192.161.30 +MX,SANANDRESCHOLULA,PUE,19.05,-98.30,23.215.15.22 +AT,PIRKA,"",47.00,15.38,195.145.147.109 +US,DYERSBURG,TN,36.0753,-89.423,23.220.100.224 +US,CEDAR,MN,45.3385,-93.2617,23.67.60.223 +US,APPLING,GA,33.6237,-82.2874,23.79.240.36 +US,MERRIMACK,NH,42.8551,-71.5193,209.170.113.237 +CA,VANDERHOOF,BC,54.02,-124.02,24.244.17.205 +US,EMMAUS,PA,40.5173,-75.5037,23.67.242.139 +US,CRANBERRYTWP,PA,40.6999,-80.1268,96.6.47.120 +CN,YIZHUANG,JS,34.17,117.58,184.50.87.178 +US,FRASER,MI,42.5384,-82.9497,69.22.154.209 +RS,IN,"",43.45,19.32,2.20.45.102 +HK,TUENMUN,"",22.40,113.98,23.76.205.111 +US,OCEANSPRINGS,MS,30.4180,-88.7558,165.254.138.165 +TG,LOME,"",6.13,1.22,77.67.41.227 +US,JACKSONVILLEBEACH,FL,30.3318,-81.6555,23.79.240.36 +US,WINSLOW,AZ,35.1934,-110.3619,65.116.149.102 +US,MAGNA,UT,40.7034,-112.1122,184.50.26.179 +UA,KALUSH,"",49.02,24.37,2.20.142.173 +US,WINOOSKI,VT,44.4955,-73.1839,165.254.48.150 +US,PINETOWN,NC,35.6052,-76.8394,184.28.17.55 +HU,SZEKESFEHERVAR,"",47.20,18.42,23.14.94.228 +FR,MARTRESDEVEYRE,"",45.68,3.20,88.221.83.118 +GR,KAVALA,"",40.94,24.40,93.186.137.228 +DK,ARHUS,"",56.15,10.22,213.155.156.206 +CN,ZHANGZHOU,FJ,24.52,117.67,184.50.87.176 +IN,KHARAGPUR,WB,22.33,87.33,96.17.182.130 +US,SAFETYHARBOR,FL,28.0080,-82.6963,23.33.186.101 +MG,ANTSIRABE,"",-19.85,47.03,195.10.8.202 +IL,MAGEN,"",31.30,34.43,212.25.69.136 +TH,BANKOK,"",13.58,100.22,88.221.15.111 +US,HOLMDEL,NJ,40.3764,-74.1727,23.220.148.122 +US,MONTEVALLO,AL,33.1388,-86.8879,23.79.240.36 +GB,SEACROFT,EN,53.82,-1.45,23.67.255.106 +FR,SAINTCHAMOND,"",45.47,4.50,2.16.117.212 +PW,KOROR,"",7.33,134.48,23.76.205.111 +US,BELEN,NM,34.5756,-106.5882,23.61.195.165 +US,MONAHANS,TX,31.5378,-102.956,64.145.95.141 +US,QUITMAN,GA,30.7559,-83.5353,184.84.180.68 +DE,PUCHHEIM,BY,48.15,11.35,84.53.175.92 +US,FAITH,SD,44.8511,-102.1289,23.74.8.61 +CN,DAQING,HL,46.58,125.00,184.51.199.132 +US,LAGUNABEACH,CA,33.5745,-117.7868,184.50.26.192 +IQ,SULAYMANIYAH,"",34.03,44.82,195.145.147.107 +US,FAIRVIEWHEIGHTS,IL,38.5952,-90.0039,204.93.47.220 +US,BALLSTONSPA,NY,43.0020,-73.8759,107.14.38.217 +FR,SAINTPRIEST,"",46.45,2.17,2.16.117.190 +US,ALAMOSA,CO,37.4690,-105.8365,107.14.32.228 +CN,LEDONG,HI,18.75,109.17,72.246.191.19 +US,MARGARETVILLE,NY,42.1471,-74.6599,165.254.48.155 +RO,BANCA,"",46.35,27.28,2.22.52.101 +PL,USTKA,"",54.58,16.85,77.67.96.114 +US,RINCON,GA,32.2490,-81.2731,23.79.240.36 +AT,STEINHAUS,"",47.62,15.80,195.145.147.109 +US,MADISONHEIGHTS,MI,42.5080,-83.103,23.63.227.227 +RU,NAKHODKA,"",51.63,43.97,80.239.237.231 +IN,PONDICHERRY,PY,11.93,79.83,80.239.237.230 +NA,TSUMEB,"",-19.23,17.72,41.193.163.45 +US,INDIANTRAIL,NC,35.0963,-80.6145,209.18.41.27 +RU,RAY,"",58.30,40.12,80.239.237.231 +PL,FRANK,"",53.90,18.25,2.22.52.101 +TH,KRABI,"",8.07,98.92,203.106.85.113 +RU,YEISK,"",46.70,38.28,2.22.52.102 +US,BARNSTABLE,MA,41.7011,-70.3019,184.25.109.196 +CN,TONGLING,AH,30.95,117.78,184.50.87.178 +DE,PFORZHEIM,BW,48.88,8.70,23.14.94.214 +US,COOPERSTOWN,NY,42.7228,-74.8929,209.18.41.27 +US,VALENTINE,NE,42.4840,-100.7562,184.27.120.65 +HU,HAJDUNANAS,"",47.85,21.43,23.14.94.228 +PR,ARECIBO,"",18.4739,-66.7295,72.164.253.83 +FR,BOBIGNY,"",48.90,2.45,90.84.50.230 +US,POWHATAN,VA,37.5492,-77.935,63.130.161.239 +TW,CHANGHUA,"",24.08,120.53,23.76.205.111 +US,STEUBENVILLE,OH,40.3582,-80.6994,184.28.17.76 +PH,TONDO,"",14.62,120.97,184.84.239.186 +DK,GALTEN,"",56.15,9.92,2.21.240.40 +NL,MIERLO,"",51.45,5.62,95.101.2.112 +UA,BERDYANSK,"",46.75,36.79,2.21.240.61 +VN,TRAI,"",17.12,106.95,184.84.239.175 +US,POWELL,OH,40.1701,-83.0808,107.14.38.227 +US,FAIRFAXSTATION,VA,38.7497,-77.3141,23.212.53.64 +AT,WELS,"",48.17,14.03,23.14.94.228 +US,LAMPASAS,TX,31.1064,-98.2303,96.17.163.161 +US,VILLAPARK,IL,41.8812,-87.9751,107.14.38.224 +US,NEWLEXINGTON,OH,39.7095,-82.1925,107.14.38.224 +MY,BATUPAHAT,"",1.85,102.93,203.106.85.195 +US,SHIRLEY,NY,40.7965,-72.8753,23.61.195.165 +BA,GRUDE,"",43.81,17.45,23.14.94.228 +AR,CARBONI,"",-35.20,-59.33,190.98.167.220 +US,BELLWOOD,IL,41.8827,-87.8764,23.67.60.223 +US,EXCELSIOR,MN,44.8924,-93.5895,23.67.60.217 +US,CEDARTOWN,GA,33.9973,-85.2758,72.246.247.30 +PL,SWINOUJSCIE,"",53.92,14.25,2.22.52.109 +US,NEOSHO,MO,36.8753,-94.3946,23.77.234.11 +VN,THUDUC,"",10.85,106.75,23.5.165.167 +CH,SCHAFFHAUSEN,"",47.70,8.63,193.247.167.214 +JP,SAKAE,30,33.65,135.40,23.61.250.108 +US,CHAPIN,SC,34.1436,-81.3335,209.18.41.27 +US,HOLLY,MI,42.7970,-83.603,184.27.120.65 +US,HARDIN,MT,45.8343,-107.7879,67.131.104.6 +BE,HASSELT,"",50.93,5.33,23.62.100.154 +JP,ASAHIKAWA,01,43.77,142.37,72.246.184.81 +RU,YUZHNOSAKHALINSK,"",46.95,142.74,96.7.251.97 +US,JOHNSISLAND,SC,32.6897,-80.0874,96.16.12.216 +US,LEITCHFIELD,KY,37.4975,-86.3182,63.216.54.216 +US,BASIN,WY,44.3702,-108.0775,184.27.179.181 +GB,STAPLE,EN,51.25,1.25,92.122.54.12 +UA,KREMENCHUK,"",49.07,33.42,80.239.149.123 +PK,SIALKOT,"",30.92,71.85,165.254.144.25 +US,RANDOMLAKE,WI,43.5753,-87.9876,23.79.255.149 +BG,RUSE,"",43.83,25.95,2.20.45.104 +US,BRAINERD,MN,46.2895,-94.0683,65.113.249.8 +CO,CUCUTA,"",7.90,-72.52,190.90.221.149 +US,BELLEGLADE,FL,26.5243,-80.6241,184.28.184.6 +IN,TADEPALLEGUDEM,AP,16.83,81.50,23.205.118.106 +US,MANDAN,ND,46.7289,-100.9833,107.14.38.217 +US,STREETSBORO,OH,41.2431,-81.3428,107.14.38.217 +BG,BALKAN,"",41.77,25.57,93.186.137.228 +US,WOODBINE,MD,39.3345,-77.0694,184.27.45.150 +GB,LANCING,EN,50.82,-0.33,173.222.211.190 +US,MERIDEN,CT,41.5330,-72.7742,184.29.107.38 +US,HAYMARKET,VA,38.8726,-77.6484,23.192.161.21 +US,DEDHAM,MA,42.2464,-71.1775,184.25.109.213 +SE,LUND,M,55.70,13.18,23.65.29.106 +MF,MARIGOT,"",18.07,-63.08,2.20.243.45 +GR,KALAMAKI,"",37.92,23.72,23.14.94.214 +FR,MAROLLESENHUREPOIX,"",48.57,2.30,2.16.117.200 +DE,WETZLAR,HE,50.55,8.50,92.122.207.179 +NA,WALVISBAY,"",-22.96,14.51,41.193.163.45 +BR,CRICIUMA,PR,-26.02,-51.72,187.59.4.147 +US,SKOWHEGAN,ME,44.8163,-69.6519,165.254.48.155 +MZ,MOCAMBIQUE,"",-17.07,36.75,165.165.46.38 +CN,YUNCHENG,SX,35.02,110.99,72.246.191.16 +US,NEWPORTCOAST,CA,33.5768,-117.7458,184.50.26.204 +US,SHAMOKINDAM,PA,40.8488,-76.8203,184.26.44.40 +SL,FREETOWN,"",8.49,-13.23,63.80.12.205 +US,GRASONVILLE,MD,38.9427,-76.1976,168.143.243.33 +US,FORSYTH,GA,33.0857,-83.918,72.246.247.30 +CZ,JICIN,"",50.43,15.35,2.20.142.166 +TR,TUZLA,"",40.50,30.52,23.62.237.138 +US,GRAFTON,WI,43.3305,-87.9299,65.113.249.8 +US,FREEBURG,IL,38.3845,-89.9186,96.17.14.15 +BE,MARAIS,"",50.55,4.32,23.62.100.154 +SA,YANBU,"",24.09,38.05,23.215.60.48 +US,KINGSMOUNTAIN,NC,35.2471,-81.3891,96.16.12.228 +US,TAOS,NM,36.4227,-105.5099,204.2.223.91 +US,CHICKASHA,OK,34.9953,-97.9747,173.197.194.159 +US,NATCHITOCHES,LA,31.7831,-93.1496,23.5.164.143 +US,EDEN,NY,42.6450,-78.8782,107.14.38.218 +US,EDGEWOOD,MD,39.4327,-76.2984,184.27.45.150 +US,SACO,ME,43.5496,-70.476,107.14.38.218 +CA,YARMOUTH,NS,43.83,-66.12,184.27.45.150 +US,MARLBORO,NJ,40.3194,-74.2497,184.26.44.38 +DE,LUNEBURG,NI,53.25,10.40,195.95.193.147 +US,LITCHFIELDPARK,AZ,33.5445,-112.5171,184.50.26.201 +GB,STOCKTONONTEES,EN,54.58,-1.42,23.67.255.106 +US,COMMERCE,TX,33.3007,-95.9347,184.26.93.116 +SK,PRESOV,"",49.00,21.25,23.62.237.137 +DZ,BATNA,"",35.56,6.18,77.67.96.114 +US,RUNNEMEDE,NJ,39.8519,-75.0768,23.67.60.223 +MZ,MOZAMBIQUE,"",-15.03,40.74,41.193.163.45 +US,BOALSBURG,PA,40.7669,-77.7668,23.192.161.16 +AU,BENDIGO,VIC,-36.77,144.28,210.11.142.67 +CZ,TABOR,"",49.42,14.67,23.62.237.138 +US,BERRIENSPRINGS,MI,41.9566,-86.3987,23.67.60.217 +US,HOLLIDAYSBURG,PA,40.4448,-78.3256,184.28.17.55 +NO,BODO,"",67.28,14.38,213.155.156.206 +RU,DIVNOGORSK,"",55.96,92.36,2.21.240.40 +US,REDHOUSE,WV,38.5624,-81.9059,184.28.17.76 +AT,NEUHAUS,"",48.00,16.05,195.145.147.101 +CN,XINGYI,GZ,25.05,104.98,72.246.191.16 +HK,WANCHAI,"",22.28,114.17,23.76.205.90 +ID,LUWUK,"",-6.28,106.18,23.0.162.40 +US,BATTLEGROUND,WA,45.8003,-122.4981,23.212.59.85 +DE,INGOLSTADT,BY,48.77,11.43,92.122.207.164 +FI,KOKKOLA,"",61.50,28.20,92.122.215.89 +RO,ROMAN,"",46.92,26.92,88.221.93.157 +AT,KLAGENFURT,"",46.62,14.31,195.145.147.109 +AU,MARIBYRNONG,VIC,-37.78,144.88,60.254.143.211 +US,SLOUGHHOUSE,CA,38.5091,-121.107,128.241.89.70 +US,VILLEPLATTE,LA,30.7127,-92.2634,23.212.53.64 +DE,OBERHAUSEN,NW,51.47,6.85,2.20.142.166 +GB,SALFORD,EN,52.03,-0.63,88.221.87.94 +GB,GIFFORD,SC,55.90,-2.73,23.212.108.28 +US,BALDWINSVILLE,NY,43.1825,-76.3664,184.26.44.40 +NO,ARENDAL,"",58.46,8.77,2.21.240.40 +IN,NAMAKKAL,TN,11.23,78.17,23.205.118.106 +CZ,HODONIN,"",49.83,15.78,195.27.155.188 +US,MANOR,TX,30.3520,-97.5205,96.17.163.161 +PL,ISKRZYCZYN,"",49.82,18.75,23.74.24.69 +CN,WUHU,AH,31.35,118.37,184.50.87.178 +UA,KRAMATORSK,"",48.72,37.53,80.239.237.231 +AR,LUJAN,"",-34.57,-59.10,2.21.240.40 +DE,NUSSE,SH,53.67,10.58,92.122.207.179 +NL,EDE,"",52.03,5.67,95.101.2.112 +US,OWATONNA,MN,44.0575,-93.2082,184.85.215.165 +US,SCIO,OR,44.6708,-122.6996,23.212.59.85 +FI,SEINAJOKI,"",62.80,22.83,2.21.240.40 +US,CHERRYVILLE,NC,35.3791,-81.3649,96.16.12.216 +IN,ATTUR,TN,12.73,79.95,23.205.118.106 +PH,TOWER,"",6.18,125.13,23.76.205.111 +US,TRUSSVILLE,AL,33.6426,-86.5754,165.254.138.175 +PT,PRIME,"",40.63,-7.83,195.22.14.133 +ES,MORON,"",41.42,-2.42,2.20.44.118 +CZ,KTIS,"",48.92,14.13,23.62.237.133 +CZ,NYRANY,"",49.72,13.20,195.27.155.188 +US,BONNERSPRINGS,KS,39.0619,-94.8881,23.77.234.35 +BA,BRCKO,"",44.88,18.81,95.101.34.105 +US,GODDARD,KS,37.6682,-97.5892,174.76.226.117 +US,PELZER,SC,34.6459,-82.4278,23.79.240.36 +US,GRANVILLE,OH,40.0812,-82.5297,77.67.86.217 +AU,ROSEBERY,NSW,-33.92,151.20,202.7.177.87 +US,LOUDONVILLE,OH,40.6534,-82.2246,23.74.8.8 +AU,ULTIMO,NSW,-33.88,151.20,104.72.70.96 +DE,BOTTROP,NW,51.52,6.92,2.22.61.99 +GR,KOZANI,"",40.30,21.78,23.14.94.228 +US,LAKEOZARK,MO,38.2106,-92.6582,204.93.47.220 +US,GLENCARBON,IL,38.7582,-89.9728,23.212.53.75 +NG,ODUA,"",4.92,6.45,90.84.53.225 +US,SMARR,GA,32.9834,-83.8751,63.234.249.61 +US,BELLEVERNON,PA,40.1536,-79.8119,23.192.161.16 +US,WINNFIELD,LA,31.8850,-92.6017,23.5.164.146 +HU,ANGYALFOLD,"",47.53,19.07,23.14.94.228 +US,CARO,MI,43.4866,-83.3855,65.113.249.8 +US,IGNACIO,CO,37.0891,-107.6496,64.129.104.132 +ID,MADIUN,"",-7.62,111.52,23.0.162.40 +US,PERRYSVILLE,OH,40.6625,-82.3165,23.215.15.22 +UA,KHIZHA,"",48.10,23.20,192.80.13.117 +IT,PARCO,"",38.05,13.30,96.17.180.155 +US,HEPHZIBAH,GA,33.2810,-82.1107,23.79.240.36 +US,DETROITLAKES,MN,46.9503,-95.6596,198.63.196.214 +US,HEBRON,KY,39.0882,-84.7043,107.14.38.217 +IN,ABHANPUR,CT,21.05,81.72,124.124.252.159 +US,LITTLERIVER,SC,33.8867,-78.6627,209.18.41.27 +IN,KANPUR,UP,26.47,80.35,23.57.76.18 +US,CHARDON,OH,41.5761,-81.1919,107.14.38.218 +HU,BALATON,"",48.10,20.32,23.14.94.214 +GM,BANJUL,"",13.45,-16.58,23.76.205.90 +US,TWINSBURG,OH,41.3169,-81.4404,107.14.38.218 +US,MOUNTPOCONO,PA,41.1358,-75.3944,23.67.242.156 +RO,TATARANI,"",44.90,26.03,80.239.222.169 +DZ,BLIDA,"",36.47,2.83,213.248.108.244 +US,SILOAMSPRINGS,AR,36.1693,-94.458,23.215.15.9 +AT,GROSSENDORF,"",48.05,14.05,195.145.147.109 +US,SEVERN,MD,39.1227,-76.6832,23.192.161.16 +RU,KURILSK,"",45.23,147.88,77.67.27.235 +US,BIRDSBORO,PA,40.2313,-75.8555,63.216.54.231 +US,BARBOURVILLE,KY,36.8650,-83.9507,184.27.45.150 +AR,ROJAS,"",-34.20,-60.73,80.239.237.230 +US,PALATINE,IL,42.1106,-88.0342,107.14.38.227 +RU,ULANUDE,"",51.83,107.62,184.51.199.145 +CA,CASTLEGAR,BC,49.32,-117.67,184.27.179.159 +AR,RIOCUARTO,"",-33.13,-64.35,80.239.237.231 +US,BURLINGAME,CA,37.5670,-122.3669,96.17.12.44 +US,KOHLER,WI,43.7428,-87.7817,23.74.8.24 +IN,GANDHIDHAM,GJ,23.08,70.13,23.211.135.66 +US,POULSBO,WA,47.7571,-122.6233,165.254.1.165 +KR,TAEGU,"",35.87,128.60,125.56.214.166 +RU,PENZA,"",53.20,45.00,2.22.52.109 +TR,BOGAZICI,"",37.52,30.07,23.14.94.224 +RU,PANFILOVA,"",56.00,39.10,2.21.240.61 +US,WESTLAKE,LA,30.2637,-93.2773,23.215.15.22 +BR,LIMEIRA,SP,-22.56,-47.40,187.59.4.154 +US,WOODRUFF,SC,34.7461,-82.0164,165.254.138.175 +US,GOLDTHWAITE,TX,31.3914,-98.5866,23.212.53.75 +CA,GASPE,QC,48.83,-64.48,184.27.120.65 +PL,BIALAPODLASKA,"",52.03,23.13,77.67.96.114 +US,FORTEDWARD,NY,43.2300,-73.5588,107.14.38.217 +US,BONAIRE,GA,32.5074,-83.5644,184.51.35.226 +US,LONGPOND,PA,41.0663,-75.4541,184.26.44.38 +IR,CHAMRAN,"",35.17,49.93,77.67.96.114 +US,NEWBOSTON,TX,33.4799,-94.4582,23.215.15.9 +TR,GENEL,"",40.88,39.57,23.74.24.66 +US,PROSPECT,KY,38.3571,-85.5869,107.14.38.217 +US,CLOVER,SC,35.1039,-81.2451,72.246.247.5 +US,RANCHOMIRAGE,CA,33.7825,-116.4136,184.50.26.192 +US,OLNEY,IL,38.7221,-88.0876,23.74.8.8 +US,MADRAS,OR,44.6442,-121.0642,67.131.104.14 +DE,LINDAU,BY,47.55,9.68,195.145.147.109 +US,ZEBULON,NC,35.8277,-78.3112,96.16.12.216 +US,BAKERCITY,OR,44.7595,-117.7162,165.254.144.32 +US,HUGOTON,KS,37.1182,-101.3229,23.215.15.22 +DE,ESPELKAMP,NW,52.38,8.62,92.122.207.179 +UA,GORODOK,"",49.60,29.20,2.22.52.109 +FR,TASSIN,"",45.77,4.78,2.16.117.190 +CA,MALTON,ON,43.70,-79.63,72.246.43.237 +SG,TAISENG,"",1.34,103.90,124.155.222.130 +DE,ALBERT,BW,47.58,8.12,80.157.170.154 +FR,SAINTDIDIERENVELAY,"",45.30,4.28,2.16.117.190 +FR,BONDY,"",48.90,2.47,2.16.117.200 +CZ,KURIM,"",49.30,16.53,2.22.52.102 +US,GLENWOODSPRINGS,CO,39.6119,-107.29,23.212.53.75 +US,LITTLESTOWN,PA,39.7552,-77.119,212.25.69.145 +RU,SOCHI,"",43.60,39.73,2.21.240.61 +CA,TIVERTON,ON,44.27,-81.54,209.148.192.61 +US,VINTON,VA,37.2726,-79.7653,23.220.148.108 +AU,SHEPPARTON,VIC,-36.38,145.40,202.7.177.87 +US,BRASELTON,GA,34.1410,-83.7809,23.79.240.48 +FI,NOKIA,"",61.47,23.50,95.101.2.122 +RU,YUG,"",56.25,56.05,2.21.240.61 +AT,LEBRING,"",46.85,15.54,195.145.147.107 +NL,NIJMEGEN,"",51.83,5.87,92.122.189.114 +IT,SESTO,"",45.53,9.23,193.45.15.198 +FI,ALAJARVI,"",63.00,23.82,2.21.240.40 +HU,DEBRECEN,"",47.53,21.63,23.14.94.220 +DE,SAARBURG,RP,49.60,6.55,95.101.2.112 +RO,BUSTENI,"",45.40,25.53,81.196.26.198 +UA,CHERNIHIV,"",51.50,31.30,23.14.94.224 +US,LAKEGENEVA,WI,42.5685,-88.4719,107.14.38.217 +IN,TEKANPUR,MP,25.98,78.27,96.17.182.130 +US,NORTHBEND,OR,43.4574,-123.9916,184.27.179.179 +RO,SIGHETUMARMATIEI,"",47.93,23.88,81.196.26.236 +US,GIDDINGS,TX,30.1637,-96.9376,65.116.149.89 +US,KANAB,UT,37.2711,-111.7696,165.254.137.75 +FR,CARPENTRAS,"",44.05,5.05,2.16.117.190 +PL,DZIALDOWO,"",53.23,20.18,2.22.52.101 +US,CHEBOYGAN,MI,45.5327,-84.3636,23.63.227.227 +PL,SUPRASL,"",53.22,23.35,80.157.149.129 +DE,HERFORD,NW,52.13,8.68,92.122.207.179 +US,CALIFORNIACITY,CA,35.1256,-117.9853,184.50.26.194 +DE,MONCHENGLADBACH,NW,51.20,6.43,80.157.170.158 +AU,GEELONG,VIC,-38.16,144.35,104.72.70.96 +US,OAKGROVE,MO,39.0160,-94.144,23.67.60.222 +RU,VYAZMA,"",56.49,35.78,80.239.222.169 +US,ISELIN,NJ,40.5710,-74.3169,184.26.44.38 +PL,CHOJNICE,"",53.70,17.57,80.239.222.169 +US,ATTALLA,AL,34.0771,-86.0689,23.79.240.36 +US,GATESVILLE,TX,31.4272,-97.7097,23.215.15.9 +IT,CARBONE,"",38.23,16.25,23.76.205.111 +US,PRESTONSBURG,KY,37.6405,-82.8256,184.27.45.157 +RS,NOVISAD,"",45.25,19.84,2.20.45.104 +CH,UITIKON,"",47.37,8.47,193.45.15.199 +SE,BORLANGE,W,60.48,15.42,82.96.58.85 +US,PINEGROVE,CA,38.4023,-120.6508,63.217.232.17 +US,TECUMSEH,OK,35.2189,-97.0168,205.185.195.170 +IT,STELLA,"",44.45,10.80,2.18.240.114 +FI,KOUVOLA,"",60.33,24.15,213.155.156.207 +DE,CRIMMITSCHAU,SN,50.82,12.38,195.95.193.150 +US,CIBOLO,TX,29.5774,-98.2236,23.5.164.146 +FR,LANGUEUX,"",48.50,-2.72,2.16.117.200 +US,EASTPROSPECT,PA,39.9710,-76.5165,23.192.161.21 +US,ELRENO,OK,35.5525,-97.9651,23.215.15.22 +US,LOUISIANA,MO,39.4061,-91.0955,96.17.14.16 +US,EUFAULA,AL,31.9293,-85.2612,72.246.247.5 +SE,OSTERSUND,Z,63.18,14.65,2.21.240.40 +US,WARRENVILLE,IL,41.8320,-88.2281,23.67.60.220 +US,GROVER,MO,38.5699,-90.6264,96.17.14.15 +US,CIRCLEPINES,MN,45.1631,-93.1211,23.67.60.223 +US,THERMOPOLIS,WY,43.7189,-108.4422,184.27.179.159 +FR,VENISSIEUX,"",45.68,4.88,2.16.117.200 +LT,NAUJOJIAKMENE,"",56.32,22.90,217.212.227.25 +RO,SEBES,"",45.72,25.03,81.196.26.198 +US,TERRABELLA,CA,35.9407,-119.0558,65.113.249.8 +VI,CHARLOTTEAMALIE,"",18.3436,-64.9314,192.204.11.246 +US,CRAIG,CO,40.7169,-107.7139,107.14.32.235 +CH,WINTERTHUR,"",47.50,8.75,193.247.167.214 +AU,OAKLEIGH,VIC,-37.90,145.10,60.254.143.211 +IT,TORREPELLICE,"",44.82,7.22,2.18.240.95 +US,NEWPALESTINE,IN,39.7310,-85.9032,23.67.60.217 +FR,MAYENNE,"",48.30,-0.62,2.16.117.190 +JP,ICHINOSEKI,03,38.92,141.13,72.246.191.16 +GB,SIDMOUTH,EN,50.68,-3.25,72.246.43.237 +DE,OFFENBACH,HE,50.10,8.77,84.53.146.39 +US,DIBERVILLE,MS,30.4863,-88.9554,165.254.138.165 +TH,CHONBURI,"",13.37,100.98,61.19.12.164 +IN,KOL,UL,30.50,77.92,23.57.69.161 +JP,HIKARI,35,33.96,131.95,118.155.230.136 +SG,CHANGI,"",1.34,103.96,23.75.23.135 +US,OAKLYN,NJ,39.9079,-75.0838,184.26.44.38 +US,HILLIARD,OH,40.0220,-83.1807,107.14.38.227 +US,CARLSTADT,NJ,40.8256,-74.0623,23.67.244.226 +AT,FIEBERBRUNN,"",47.48,12.55,195.145.147.108 +US,VERMILLION,SD,42.8915,-96.9263,23.212.53.64 +US,WALL,SD,43.9288,-102.204,23.63.227.214 +IR,SARI,"",36.57,53.06,96.17.182.130 +SK,VELICNA,"",49.22,19.25,23.14.94.220 +US,PELLA,IA,41.4226,-92.9246,63.216.54.229 +AR,PUNTAALTA,"",-38.88,-62.08,190.98.167.220 +MX,CIUDADVICTORIA,TAM,23.73,-99.13,165.254.16.86 +US,SOUTHGLENSFALLS,NY,43.2897,-73.6312,107.14.38.217 +US,PARLIN,NJ,40.4576,-74.306,184.26.44.38 +US,OGALLALA,NE,41.0603,-101.6294,23.215.15.22 +PH,PASAY,"",14.55,121.00,58.71.107.119 +CZ,ZNOJMO,"",48.85,16.05,23.62.237.135 +NL,LEEUWARDEN,"",53.20,5.78,2.16.153.150 +RU,SATIS,"",54.82,43.13,213.155.156.212 +IT,ROZZANO,"",45.37,9.15,195.22.200.221 +US,MARTINSVILLE,VA,36.7249,-79.8574,184.26.44.38 +DE,RHEIN,NW,50.85,7.70,2.20.142.166 +IN,RATNAGIRI,MH,16.98,73.30,117.239.240.96 +AT,DIETACH,"",48.08,14.42,195.145.147.109 +CA,SAINTEUSTACHE,QC,45.57,-73.90,67.69.197.92 +US,POULTNEY,VT,43.5323,-73.1932,165.254.48.155 +US,CHANHASSEN,MN,44.8569,-93.5486,204.93.47.216 +TH,NUA,"",18.65,101.03,202.183.253.37 +US,CRESTWOOD,KY,38.3420,-85.4306,23.220.100.223 +CA,HEARST,ON,49.70,-83.67,72.246.43.237 +AT,THERESIENFELD,"",47.85,16.23,195.145.147.108 +FR,FROMONT,"",48.25,2.50,2.16.117.200 +ID,CIANJUR,"",-6.82,107.13,23.0.162.21 +US,PAPILLION,NE,41.1138,-96.0413,23.79.255.153 +KZ,ZHEZKAZGAN,"",47.78,67.77,217.212.227.31 +US,THOMSON,GA,33.5142,-82.516,23.79.240.36 +CR,GUADALUPE,"",9.95,-84.05,23.74.2.7 +PT,BARCARENA,"",38.73,-9.28,195.22.14.134 +TM,TURKMENISTAN,"",40.47,62.22,2.20.142.166 +US,BARRON,WI,45.3978,-91.8834,23.74.8.8 +US,MABANK,TX,32.3389,-96.1042,23.212.53.75 +US,RUSK,TX,31.7956,-95.1946,67.131.44.150 +US,PINSON,AL,33.7345,-86.6508,23.220.100.223 +CZ,CHRUDIM,"",49.95,15.80,23.62.237.138 +US,HALLETTSVILLE,TX,29.3984,-96.8256,23.215.15.22 +US,CASSELTON,ND,46.8908,-97.241,23.74.8.24 +IE,GALWAY,"",53.27,-9.05,88.221.222.33 +JP,YAMANASHI,22,34.80,137.90,72.246.191.16 +IN,CHANDAUSI,UP,28.45,78.77,23.205.118.106 +IN,KALAMBOLI,MH,19.03,73.10,96.17.180.155 +US,HAYTI,MO,36.2659,-89.7083,96.17.14.15 +CN,SANMING,FJ,26.40,117.20,184.84.239.175 +DE,BINDLACH,BY,49.98,11.61,23.74.24.69 +CH,MURTEN,"",46.93,7.12,213.254.212.102 +US,SAMMAMISH,WA,47.6302,-122.0537,23.212.59.63 +AU,SOUTHYARRA,VIC,-37.83,144.98,23.205.116.7 +UA,SUMY,"",50.92,34.78,80.239.222.190 +US,KUNA,ID,43.3407,-116.2859,206.104.149.146 +PL,BARCINWIES,"",52.88,17.95,2.22.52.101 +US,TANEYTOWN,MD,39.6723,-77.1742,23.67.242.156 +US,PARKRAPIDS,MN,46.9966,-95.0029,184.85.215.170 +US,SHEPHERDSVILLE,KY,37.9787,-85.6645,63.216.54.231 +TR,KAVACIK,"",41.48,27.90,23.74.24.69 +RU,NIZHNEKAMSK,"",55.64,51.82,2.21.240.40 +US,ANTIGO,WI,45.1268,-89.1724,23.74.8.8 +US,WESTBLOOMFIELD,MI,42.5418,-83.3806,184.84.180.68 +FR,ISSYLESMOULINEAUX,"",48.82,2.27,2.16.117.190 +LV,VENTSPILS,"",57.39,21.56,23.14.94.224 +US,RISINGSUN,MD,39.6875,-76.0358,209.48.37.183 +US,BARNARD,MO,40.1964,-94.7908,184.51.147.33 +UA,POLE,"",48.53,25.38,46.33.70.216 +FR,CASTELGINEST,"",43.70,1.43,2.16.117.200 +SE,KINNARP,O,58.07,13.52,213.155.156.207 +US,SCOTTSBURG,IN,38.6926,-85.8877,107.14.38.224 +US,IOLA,KS,37.9552,-95.4332,23.215.15.22 +PH,PASIG,"",14.58,121.08,23.76.205.111 +IR,GARMSAR,"",35.33,52.22,23.215.60.48 +US,BALLINGER,TX,31.7639,-99.8991,23.212.53.75 +US,AMBRIDGE,PA,40.6018,-80.2094,23.192.161.21 +FR,LESCAR,"",43.33,-0.42,2.16.117.190 +US,PROSPECTHEIGHTS,IL,42.1027,-87.9288,23.67.60.222 +US,SISSETON,SD,45.7041,-96.9842,23.79.255.153 +DE,WINTERBERG,NW,51.20,8.53,23.14.94.224 +US,RIOGRANDECITY,TX,26.5735,-98.695,184.26.93.116 +US,NORTHCHICAGO,IL,42.3271,-87.865,65.113.249.11 +US,ANNA,TX,33.3451,-96.5758,23.5.164.146 +US,WIMBERLEY,TX,30.0586,-98.15,23.61.195.160 +CA,STREETSVILLE,ON,43.58,-79.72,72.246.43.232 +JP,KOFU,19,35.65,138.58,117.104.139.162 +DE,HENSTEDTULZBURG,SH,53.78,10.00,2.20.142.166 +US,MINOA,NY,43.0745,-76.0083,107.14.38.224 +IT,PADOVA,"",45.42,11.88,193.45.15.198 +US,MONUMENT,CO,39.0574,-104.9038,184.84.180.68 +CZ,KLECANY,"",50.18,14.42,23.62.237.137 +US,FORTBELVOIR,VA,38.6990,-77.1368,184.28.17.76 +US,COHOES,NY,42.7824,-73.7303,107.14.38.217 +US,NYACK,NY,41.0938,-73.9254,69.31.77.208 +US,HOULTON,ME,46.1163,-67.9329,23.79.240.36 +US,CHANNELVIEW,TX,29.7912,-95.1165,96.17.163.165 +US,SILVERTHORNE,CO,39.7695,-106.1063,184.84.180.101 +NL,COEVORDEN,"",52.67,6.75,92.122.189.85 +VI,SAINTTHOMAS,"",18.3436,-64.9314,72.164.253.73 +RU,NIKOLSKOE,"",54.29,35.88,2.21.240.61 +US,MOUNTCARMEL,IL,38.4145,-87.8638,23.74.8.8 +US,RIPLEY,WV,38.8125,-81.6945,96.17.9.14 +US,STEVENSVILLE,MI,42.0039,-86.5132,23.67.60.220 +GB,BURNLEY,EN,53.80,-2.23,184.27.139.11 +US,CELINA,OH,40.5555,-84.6061,107.14.38.218 +RO,SIGHET,"",47.93,23.88,88.221.93.157 +AT,SANKTJOHANNAMWALDE,"",48.12,13.28,23.14.94.224 +ID,MANADO,"",1.48,124.85,23.0.162.21 +DE,MUENCHEBERG,BB,52.50,14.13,195.95.193.134 +US,KUTZTOWN,PA,40.5336,-75.7775,23.62.238.215 +TR,SAMSUN,"",41.28,36.33,193.45.15.198 +KZ,SULU,"",44.67,61.20,88.221.15.110 +VA,VATICANCITY,"",41.90,12.45,95.101.34.105 +PL,BORYSZEW,"",52.18,21.32,2.22.52.101 +KR,BUSAN,"",35.10,129.04,61.111.58.224 +FI,HAAPAJARVI,"",60.27,24.45,193.184.164.239 +US,EADS,TN,35.2015,-89.6087,184.84.180.68 +DE,KAMPE,NI,53.08,7.83,92.122.207.179 +DE,OGE,NW,51.32,7.52,195.95.193.134 +CA,SWIFTCURRENT,SK,50.28,-107.77,184.150.187.241 +US,CHASKA,MN,44.8087,-93.6418,23.210.5.166 +US,MALONE,NY,44.7347,-74.2672,107.14.38.224 +US,PEARSALL,TX,28.8736,-99.1074,107.14.43.30 +NO,SKJOLD,"",59.52,5.58,2.21.240.61 +US,BRECKENRIDGE,CO,39.4661,-106.0618,23.212.53.64 +US,DYSART,IA,42.1670,-92.3578,65.113.249.11 +PL,MARIA,"",50.17,18.77,2.22.52.105 +US,LOSLUNAS,NM,34.7465,-106.6041,184.84.180.92 +DE,HOHENSTEINERNSTTHAL,SN,50.80,12.72,2.20.142.166 +US,CRESTONE,CO,37.9964,-105.6994,23.215.15.9 +IR,GHAZVIN,"",35.60,47.02,23.215.60.48 +CA,IQALUIT,NU,63.73,-68.50,67.69.197.95 +US,GREENCITY,MO,40.2455,-92.9523,23.215.15.32 +US,MEDICINELODGE,KS,37.2282,-98.6992,208.35.28.213 +AT,PISCHELSDORF,"",48.00,16.57,195.145.147.107 +FR,MELUN,"",48.53,2.67,2.16.117.200 +US,STEPHENSCITY,VA,39.0680,-78.1954,23.192.161.16 +ES,GETAFE,"",40.30,-3.72,2.20.44.111 +CA,LAVAL,QC,45.60,-73.73,67.69.197.92 +FR,NANTUA,"",46.15,5.62,2.16.117.190 +US,BURKESVILLE,KY,36.7332,-85.3312,65.113.249.8 +RO,LUGOJ,"",45.68,21.90,81.196.26.236 +FR,HELLEMMES,"",50.62,3.12,2.16.117.190 +DE,BLOMBERG,NW,51.12,7.72,80.157.150.192 +US,ROCKFALLS,IL,41.7267,-89.7066,23.67.60.220 +NO,ELVERUM,"",60.88,11.57,217.212.227.31 +SK,BANSKABYSTRICA,"",48.73,19.15,23.62.237.138 +DE,VIERNHEIM,HE,49.54,8.58,23.14.94.224 +DE,FREITAL,SN,51.02,13.65,195.95.193.134 +SK,STUROVO,"",47.80,18.73,23.62.237.137 +AU,PENRITH,NSW,-33.75,150.70,104.72.70.96 +US,MORGANFIELD,KY,37.6418,-87.8654,107.14.38.224 +US,OAKVALE,WV,37.3344,-80.9628,184.27.45.157 +US,SIKESTON,MO,36.9406,-89.5948,23.63.227.223 +US,PITTSTON,PA,41.2973,-75.7399,23.77.238.9 +US,INGLESIDE,TX,27.8594,-97.2055,23.215.15.9 +SI,KRANJ,"",46.24,14.36,194.25.95.225 +FR,CLICHY,"",48.90,2.30,80.239.237.231 +IN,LANKA,CT,19.23,80.77,23.79.240.36 +RU,PETROPAVLOVSKKAMCHATSKIY,"",53.02,158.65,2.21.240.40 +IN,TIRUPATI,AP,13.65,79.42,23.57.69.159 +US,SOCORRO,NM,33.8946,-106.5652,63.226.34.172 +US,COLFAX,WA,46.8882,-117.4005,192.80.13.108 +IR,YASUJ,"",30.65,51.62,184.25.157.162 +IT,MONTALCINO,"",43.05,11.48,213.144.173.198 +US,MASHPEE,MA,41.6167,-70.4906,23.67.60.223 +US,RANSON,WV,39.3053,-77.8555,23.192.161.16 +US,BUSHNELL,FL,28.6844,-82.1562,184.51.35.226 +GB,RUNCORN,EN,53.33,-2.75,23.67.255.158 +US,WILLARD,OH,41.0531,-82.7265,23.220.148.108 +US,HEADLAND,AL,31.3604,-85.3205,63.151.29.15 +FR,MULHOUSE,"",47.75,7.33,2.16.117.200 +KR,PUSAN,"",35.10,129.04,23.65.188.30 +US,CRESSON,PA,40.4517,-78.5846,23.192.161.16 +JP,KASHIBA,29,34.55,135.70,23.3.104.20 +CN,LONGYOU,ZJ,29.03,119.17,72.246.191.19 +JP,NARITA,12,35.78,140.32,202.229.2.211 +US,DELAVAN,WI,42.6189,-88.608,184.85.215.165 +US,BOLTON,CT,41.7651,-72.4389,184.25.109.213 +US,WALKER,LA,30.5547,-90.828,23.215.15.9 +DE,GERMERING,BY,48.13,11.37,195.145.147.101 +JP,ICHIKAWA,12,35.72,139.93,96.7.251.95 +HU,KOSZEG,"",47.38,16.55,23.14.94.214 +DE,MERZ,BB,52.20,14.35,195.145.147.108 +NL,HILVARENBEEK,"",51.48,5.13,92.122.189.114 +US,WETHERSFIELD,CT,41.7005,-72.6721,23.212.53.75 +UA,SUMI,"",50.92,34.78,23.14.94.224 +FR,VILLEJUIF,"",48.80,2.37,2.16.117.190 +TR,KIBRIS,"",39.88,32.99,2.20.142.166 +FR,MODANE,"",45.20,6.67,2.16.117.190 +US,SODDYDAISY,TN,35.2876,-85.1755,23.61.195.150 +CZ,BYSTRICEPODHOSTYNEM,"",49.40,17.68,23.62.237.138 +FR,LACIOTAT,"",43.17,5.60,2.16.117.200 +AR,TORTUGUITAS,"",-34.47,-58.77,190.98.167.220 +US,network,CA,,, +CN,SHANGQIU,HA,34.45,115.65,184.50.87.178 +US,CHANUTE,KS,37.6378,-95.4622,23.77.234.11 +CH,MURI,"",47.27,8.33,193.247.167.211 +PL,TYCHY,"",50.13,18.98,77.67.96.114 +US,SALINE,MI,42.1544,-83.8133,23.210.5.159 +FR,ANDREZIEUX,"",45.53,4.27,88.221.83.118 +US,GERALDINE,AL,34.3477,-86.0502,204.2.243.132 +US,QUARRYVILLE,PA,39.8731,-76.1426,23.192.161.21 +IN,CUDDAPAH,AP,14.47,78.82,23.205.118.106 +RU,PERESLAVLZALESSKIY,"",56.73,38.85,2.21.240.58 +PK,MULTAN,"",30.18,71.48,92.122.189.114 +AT,MATREIINOSTTIROL,"",47.00,12.53,195.145.147.107 +US,YOUNGTOWN,AZ,33.5903,-112.3029,63.226.34.176 +SI,SOSTANJ,"",46.38,15.05,84.53.175.90 +AT,NEUMARKT,"",48.13,15.05,88.221.93.157 +US,CORYDON,IN,38.1945,-86.1397,107.14.38.217 +US,GRIMES,IA,41.6833,-93.7869,23.67.60.217 +US,BONITA,CA,32.6730,-117.0021,63.151.119.16 +US,KNOBNOSTER,MO,38.6730,-93.5632,204.93.47.220 +DE,BERGHEIM,HE,50.35,9.08,80.157.170.158 +AR,LUISGUILLON,"",-34.80,-58.45,80.239.237.230 +RU,SOLNECHNOGORSK,"",56.18,36.98,213.155.156.207 +US,FORTTHOMAS,KY,39.0785,-84.4516,107.14.38.227 +DK,ESBJERG,"",55.47,8.45,23.65.29.93 +IN,AMALAPURAM,AP,16.58,82.02,23.57.69.156 +NG,ABUJA,"",9.25,6.93,23.212.108.8 +HN,SULACO,"",14.92,-87.27,72.246.65.37 +FI,TURKU,"",60.45,22.28,80.239.237.93 +KZ,ASYL,"",43.17,76.57,23.212.108.8 +US,INDIANOLA,IA,41.3316,-93.579,65.113.249.8 +IN,AGARPARA,WB,22.68,88.37,23.57.69.157 +US,MOREHEADCITY,NC,34.7367,-76.7587,209.18.41.27 +DE,HERBRECHTINGEN,BW,48.62,10.18,2.16.217.206 +GB,HERSHAM,EN,51.37,-0.40,23.67.255.158 +US,FREDERICKTOWN,MO,37.4979,-90.375,165.254.207.117 +IL,YAVNE,"",31.88,34.74,82.102.137.137 +US,LINCOLNCITY,OR,44.9454,-123.8611,184.27.179.187 +US,COOSBAY,OR,43.3057,-124.0564,184.27.179.187 +BY,STANTSIYA,"",53.61,30.22,80.239.222.190 +US,BAYARD,NM,32.6728,-108.0532,63.226.34.173 +US,VANALSTYNE,TX,33.4370,-96.5164,23.215.15.32 +US,KINGOFPRUSSIA,PA,40.0943,-75.3802,23.67.242.139 +US,SLATON,TX,33.4457,-101.6708,96.16.7.101 +FR,PLAISIR,"",48.82,1.95,2.16.117.190 +US,PISGAHFOREST,NC,35.2750,-82.6771,204.2.243.143 +US,CALISTOGA,CA,38.6394,-122.639,96.17.12.48 +FR,LEMANS,"",48.00,0.20,2.16.117.190 +US,CLARINDA,IA,40.7901,-95.0305,23.74.8.24 +MY,KINABALU,"",5.98,116.07,96.17.180.177 +AT,LEISACH,"",46.81,12.75,46.33.70.97 +IN,NANDED,MH,21.15,75.27,117.239.189.99 +IT,PIACENZA,"",45.02,9.67,2.18.240.95 +US,RAHWAY,NJ,40.6077,-74.2804,23.192.161.16 +MN,SUKHBAATAR,"",50.23,106.21,92.122.215.89 +BG,LOVECH,"",43.13,24.72,2.20.45.102 +NL,HAARLEM,"",52.37,4.65,92.122.189.85 +US,KINGSLAND,GA,30.8312,-81.764,63.234.249.61 +US,COLUMBIAFALLS,MT,48.4206,-114.1748,23.212.53.75 +US,TRAVELERSREST,SC,35.0688,-82.4166,72.246.247.5 +EE,JOE,"",59.43,24.58,213.155.156.212 +DE,HANSEN,NI,52.95,10.48,23.65.29.106 +IT,STEFANIA,"",44.38,11.45,193.45.15.199 +PR,VEGABAJA,"",18.4061,-66.3012,72.164.253.68 +IN,JODHPUR,RJ,26.29,73.03,96.17.182.130 +US,NEWULM,MN,44.2563,-94.471,23.67.60.220 +NL,GRONINGEN,"",53.22,6.55,2.20.243.45 +US,NEILLSVILLE,WI,44.5294,-90.6622,23.74.8.8 +NL,EERSEL,"",51.37,5.32,95.101.2.113 +NL,ARNHEM,"",51.98,5.92,2.16.153.173 +US,SYLVA,NC,35.3551,-83.1997,184.51.35.226 +SE,SKELLEFTEA,AC,64.77,20.95,2.21.240.61 +PL,LOWCE,"",49.93,22.73,80.15.235.171 +US,UNDERWOOD,MN,46.3249,-95.8405,23.74.8.8 +US,MOULTON,AL,34.4578,-87.2911,23.212.53.75 +NG,AUN,"",8.33,5.33,77.67.41.223 +US,NEVADACITY,CA,39.3517,-120.851,23.61.195.163 +UZ,NAMANGAN,"",41.00,71.67,2.21.240.61 +US,SOUTHPADREISLAND,TX,26.3706,-97.228,23.5.164.146 +IN,GOREGAON,MH,18.17,73.30,23.211.135.66 +US,GLENOLDEN,PA,39.9030,-75.2932,23.67.242.139 +US,ELBERTON,GA,34.1050,-82.81,23.79.240.36 +US,LARKSPUR,CO,39.1989,-104.8931,23.215.15.9 +AR,MARDEAJO,"",-36.72,-56.67,200.123.201.215 +IT,ASCOLIPICENO,"",42.85,13.57,2.18.240.95 +US,BERWICK,PA,41.0944,-76.241,165.254.48.142 +US,PASCAGOULA,MS,30.5698,-88.4248,24.143.197.206 +CH,LUCERNE,"",47.08,8.27,193.247.167.211 +US,PONCHATOULA,LA,30.4008,-90.3723,23.79.240.48 +US,MARFA,TX,30.1759,-104.2916,96.17.163.161 +US,IRONTON,OH,38.5450,-82.6629,96.17.9.8 +RU,BERYOZOVSKY,"",54.03,120.17,2.21.240.40 +RS,ZRENJANIN,"",45.38,20.38,2.20.45.104 +PT,MOITA,"",38.65,-8.98,195.22.14.133 +FR,SARTROUVILLE,"",48.95,2.18,2.16.117.190 +US,MARBLEFALLS,TX,30.5925,-98.2219,23.215.15.9 +ID,CIKUPA,"",-6.23,106.52,23.0.162.40 +CZ,UPICE,"",50.52,16.02,23.62.237.137 +IN,SILCHAR,AS,24.82,92.80,124.124.40.95 +JP,CHOFU,13,35.66,139.55,72.246.191.19 +IN,UJJAIN,MP,23.18,75.77,117.239.189.111 +GB,ROCHDALE,EN,53.62,-2.15,23.67.255.158 +US,EDENTON,NC,36.1056,-76.6017,96.16.12.228 +FR,FONTAINE,"",48.35,2.15,2.16.117.190 +US,WYTHEVILLE,VA,36.9511,-81.112,184.29.107.38 +EC,BABAHOYO,"",-1.82,-79.52,72.246.65.23 +IN,SANGRUR,PB,30.23,75.83,96.17.182.130 +FI,JOENSUU,"",62.60,29.77,2.21.240.40 +SA,JAZAN,"",16.89,42.55,46.33.70.216 +US,CANEY,KS,37.0586,-95.8808,69.31.59.73 +DE,ROS,BY,49.25,10.55,195.95.193.132 +AT,JERZENS,"",47.15,10.73,46.33.70.97 +US,METAMORA,IL,40.7942,-89.4075,23.79.240.36 +US,CHICOPEE,MA,42.1705,-72.6067,63.141.200.248 +US,CLEWISTON,FL,26.4660,-80.9492,23.79.240.48 +BN,SERIA,"",4.62,114.32,96.17.180.177 +US,VERADALE,WA,47.6287,-117.1938,23.212.59.85 +RU,NOGINSKAYA,"",60.78,42.68,63.216.54.236 +US,CIRCLE,MT,47.4646,-105.835,184.51.35.226 +NL,ALMELO,"",52.35,6.67,92.122.189.114 +IT,MARINO,"",42.83,13.65,46.33.73.225 +CN,DEYANG,SC,31.13,104.40,23.15.10.106 +CH,LANGENTHAL,"",47.22,7.78,193.247.167.211 +FR,ANGOULEME,"",45.65,0.15,2.16.117.200 +US,BARDSTOWN,KY,37.7964,-85.4724,107.14.38.227 +US,MUSCATINE,IA,41.4340,-91.0853,205.185.195.183 +PL,SIEMIANOWICESLASKIE,"",50.30,19.03,80.157.149.181 +IN,TIRUCHCHIRAPPALLI,TN,10.80,78.69,80.239.237.231 +US,EASTSAINTLOUIS,IL,38.6386,-90.1321,204.93.47.216 +US,PROCTORVILLE,OH,38.4900,-82.3527,23.212.53.75 +CZ,PROSTEJOV,"",49.47,17.12,23.62.237.133 +US,OAKTON,VA,38.8902,-77.3289,23.220.148.122 +HU,TATA,"",47.65,18.32,92.122.189.85 +US,HAZELCREST,IL,41.5748,-87.6813,23.67.60.220 +FR,VILLEFRANCHESURMER,"",43.70,7.32,2.16.117.200 +HU,BECSEHELY,"",46.45,16.80,195.145.147.107 +BG,PLEVEN,"",43.42,24.62,2.20.142.166 +US,MINOOKA,IL,41.4851,-88.3207,107.14.38.227 +US,FESTUS,MO,38.1363,-90.407,23.79.255.153 +ID,CENGKARENG,"",-6.15,106.72,2.22.52.102 +TH,CHIANGMAI,"",18.79,98.98,61.19.12.176 +US,NEWSTANTON,PA,40.2329,-79.6397,209.48.37.188 +US,WEEHAWKEN,NJ,40.7678,-74.0275,184.51.35.226 +US,WENONAH,NJ,39.7966,-75.1429,184.26.44.38 +US,MAYSVILLE,KY,38.5850,-83.7789,23.79.240.48 +SK,TRNAVA,"",48.37,17.60,92.122.215.67 +RU,DZERZHINSKIY,"",55.63,37.84,80.239.237.80 +US,WELCH,WV,37.3787,-81.5098,23.74.8.8 +FR,BEAUZELLE,"",43.67,1.37,2.16.117.190 +AT,GRIESKIRCHEN,"",48.23,13.83,195.145.147.109 +US,COPPEROPOLIS,CA,37.9530,-120.6995,173.223.52.70 +AR,DELVISO,"",-34.45,-58.80,190.98.167.230 +GB,GREATYARMOUTH,EN,52.63,1.75,23.67.255.158 +US,BONHAM,TX,33.5544,-96.2,23.215.15.9 +US,LAGRANGEPARK,IL,41.8338,-87.8701,23.67.60.217 +IT,SALUZZO,"",44.65,7.48,2.18.240.114 +DE,BADOLDESLOE,SH,53.82,10.38,92.122.207.179 +CA,SAINTJEAN,QC,45.30,-73.25,67.69.197.95 +CA,LORETTEVILLE,QC,46.85,-71.37,165.254.96.242 +AT,FUSSACH,"",47.48,9.67,84.53.146.34 +US,PENNSGROVE,NJ,39.6981,-75.4502,23.67.242.139 +FR,MARTIGNASSURJALLE,"",44.83,-0.77,2.16.117.200 +FR,LERAINCY,"",48.90,2.52,2.16.117.190 +US,NEWCANEY,TX,30.1594,-95.1973,96.17.163.165 +AT,EDT,"",47.87,14.68,195.145.147.108 +US,NATRONAHEIGHTS,PA,40.6420,-79.7309,65.121.209.141 +US,POPLARVILLE,MS,30.8781,-89.5858,96.17.153.157 +KR,SANGJU,"",36.41,128.15,61.111.58.229 +DE,CELLE,NI,52.62,10.08,195.245.125.114 +US,CENTER,TX,31.7586,-94.1975,64.145.68.38 +US,APOLLO,PA,40.5292,-79.5952,23.192.161.16 +US,TEANECK,NJ,40.8902,-74.0104,63.238.85.169 +AR,RAMALLO,"",-33.48,-60.02,200.123.201.215 +PL,KONIN,"",51.70,19.28,2.22.61.102 +PR,FAJARDO,"",18.3304,-65.6573,23.74.2.7 +US,PUNXSUTAWNEY,PA,40.9472,-78.981,23.67.242.156 +PL,GLOGOW,"",51.42,20.87,2.22.52.109 +US,NORTHBRANCH,MN,45.5343,-92.8964,107.14.38.217 +RU,NOYABRSK,"",63.17,75.62,2.21.240.40 +US,ZELIENOPLE,PA,40.7632,-80.1242,65.121.209.133 +RU,ALTAISK,"",51.96,85.35,80.239.237.80 +IR,ASHENA,"",36.45,49.98,184.27.45.150 +US,MARS,PA,40.7051,-80.0184,72.246.52.107 +ZA,GREENPOINT,"",-33.92,18.40,165.165.46.36 +US,BURNHAM,PA,40.6380,-77.5634,23.67.242.139 +RU,ZELENOGRAD,"",56.00,37.21,80.239.237.93 +US,WOODLANDPARK,CO,39.0237,-105.0999,23.212.53.75 +US,VALLEYCOTTAGE,NY,41.1240,-73.9363,184.51.125.79 +FR,BOURGES,"",47.08,2.40,2.16.117.200 +US,FORRESTCITY,AR,35.0264,-90.8596,23.220.100.223 +US,SANDERSVILLE,GA,33.0015,-82.8994,23.79.240.36 +SE,HALMSTAD,N,56.67,12.86,2.21.240.40 +CZ,BROD,"",49.67,14.02,23.62.237.133 +RO,COVASNA,"",45.85,26.18,2.22.52.105 +US,MIDDLESBORO,KY,36.6372,-83.7049,107.14.38.227 +US,BEND,OR,44.1187,-121.282,67.131.104.14 +SK,SKALITE,"",49.50,18.90,23.62.237.135 +US,UNIONBRIDGE,MD,39.5440,-77.1891,23.215.15.22 +PL,RAWAMAZOWIECKA,"",51.77,20.25,80.239.149.123 +HU,MISKOLC,"",48.10,20.78,23.14.94.228 +US,EMMETSBURG,IA,43.0838,-94.6785,165.254.207.111 +FR,JANZE,"",47.97,-1.50,2.16.117.190 +IN,WASHIM,MH,20.10,77.15,23.205.118.109 +US,WESTHELENA,AR,34.5741,-90.6745,23.5.164.143 +US,MARYESTHER,FL,30.4108,-86.7601,165.254.45.32 +CZ,BOSKOVICE,"",49.48,16.67,23.62.237.133 +BD,MIRPUR,"",23.57,90.62,23.57.76.18 +SS,JUBA,"",4.85,31.60,41.193.163.53 +US,CLAY,NY,43.1873,-76.1924,107.14.38.217 +US,BLACKFOOT,ID,43.2718,-112.4055,206.104.149.146 +RU,IGRA,"",57.56,53.05,2.21.240.61 +US,ROGERSVILLE,AL,34.8568,-87.316,23.220.100.223 +IN,GHATKOPAR,MH,19.08,72.90,23.14.94.214 +BG,GABROVO,"",42.62,25.17,92.122.188.161 +US,CHESTNUTHILL,MA,42.3163,-71.1603,107.14.32.235 +DE,PLAN,SN,50.93,14.13,80.157.150.201 +BD,FENI,"",23.00,91.40,96.17.180.177 +US,WEBBCITY,MO,37.1493,-94.4792,107.14.43.30 +FR,MONTFERMEIL,"",48.90,2.57,2.16.117.200 +US,RIPON,WI,43.8527,-88.8455,23.63.227.227 +FR,MONTIVILLIERS,"",49.55,0.20,88.221.15.110 +CZ,ZABREH,"",49.88,16.87,23.62.237.135 +AR,MARIANOACOSTA,"",-34.73,-58.79,190.98.167.230 +US,WATERVILLE,OH,41.4970,-83.7598,107.14.38.227 +AT,KIRCHBERGINTIROL,"",47.45,12.32,195.145.147.108 +ID,PRABUMULIH,"",-3.45,104.25,23.0.162.46 +UA,KURILOV,"",50.55,34.72,23.14.94.224 +RU,OBNINSK,"",55.10,36.61,80.239.222.167 +US,SEAGOVILLE,TX,32.6388,-96.5631,184.28.23.24 +US,CAVECREEK,AZ,33.8319,-111.9436,63.226.34.181 +US,BULLSGAP,TN,36.3360,-83.0112,23.79.240.48 +RU,NAROFOMINSK,"",55.39,36.74,2.21.240.40 +BG,KASPICHAN,"",43.32,27.17,95.101.34.105 +US,ATTLEBORO,MA,41.9304,-71.2954,23.192.161.21 +US,ROCKMART,GA,33.9615,-85.0722,23.79.240.48 +IR,BANK,"",27.87,52.03,23.62.238.215 +AU,NEWRYBAR,NSW,-28.72,153.53,104.72.70.95 +US,MCPHERSON,KS,38.4089,-97.6556,174.76.226.110 +SE,OREBRO,T,59.28,15.22,23.60.69.210 +UA,DRUZHKOVKA,"",48.62,37.55,23.14.94.228 +US,DEMOTTE,IN,41.1657,-87.2663,23.74.8.24 +GB,FLEET,EN,51.28,-0.83,23.67.71.116 +JP,TAKAYAMA,21,36.13,137.25,23.61.250.108 +AR,HUINCARENANCO,"",-34.83,-64.38,200.123.201.215 +FI,LOVIISA,"",60.45,26.23,2.21.240.40 +US,SNEADS,FL,30.7730,-84.9746,63.151.29.15 +US,CUBA,MO,38.1231,-91.4205,204.93.47.216 +GB,ENFIELD,EN,51.67,-0.07,23.3.15.11 +US,MAGEE,MS,31.8220,-89.7913,96.17.153.157 +PH,ILOILO,"",10.70,122.57,63.217.232.22 +SE,LINKOPING,E,58.42,15.62,2.21.240.40 +GR,XANTHI,"",41.13,24.88,23.14.94.214 +JP,NOMURA,36,34.05,134.10,118.155.230.132 +US,DECORAH,IA,43.3626,-91.8164,107.14.38.224 +IR,SENA,"",29.22,51.59,96.17.182.136 +RO,STEFANESTI,"",44.52,26.73,81.196.26.237 +US,MANTEO,NC,35.8834,-75.6616,184.28.127.58 +FR,EPINAYSURSEINE,"",48.95,2.32,2.16.117.200 +US,DALLASTOWN,PA,39.8950,-76.6501,23.192.161.16 +US,FORTDRUM,NY,44.1255,-75.6043,107.14.38.224 +LY,BENGHAZI,"",32.12,20.07,79.140.94.243 +US,SCHNECKSVILLE,PA,40.6716,-75.6276,184.26.44.38 +MY,KOTA,"",2.52,102.17,58.27.124.241 +BG,PANCHAREVO,"",42.60,23.42,2.20.142.173 +PL,SZCZYTNO,"",52.25,20.35,80.239.222.167 +US,KAUFMAN,TX,32.5074,-96.2414,23.212.53.64 +MY,PETALINGJAYA,"",3.08,101.65,58.26.185.142 +US,STUARTSDRAFT,VA,37.9955,-79.0396,184.27.45.157 +US,WHITESBORO,TX,33.6662,-96.8486,23.5.164.143 +US,KILLDEVILHILLS,NC,36.0144,-75.6824,23.79.240.48 +ES,ABI,"",42.47,0.43,90.84.53.193 +CZ,SEBROV,"",49.33,16.60,23.62.237.133 +RU,USSURIYSK,"",43.80,131.98,72.246.184.81 +US,CENTERVALLEY,PA,40.5452,-75.4231,184.27.45.157 +US,LAKEMARY,FL,28.7595,-81.3431,184.51.145.22 +US,DELMAR,CA,32.9697,-117.2461,63.151.119.16 +NL,DINXPERLO,"",51.87,6.48,92.122.189.114 +US,ROSELAND,NJ,40.8207,-74.3087,72.246.247.5 +PL,CZESTOCHOWA,"",50.80,19.12,80.239.222.169 +US,POLLOCKPINES,CA,38.7953,-120.4833,165.254.144.25 +US,HOLDREGE,NE,40.4958,-99.3198,65.113.249.8 +US,MERRILLVILLE,IN,41.4814,-87.338,23.67.60.220 +US,HUNTINGBURG,IN,38.3038,-86.9615,165.254.207.111 +US,EASTELMHURST,NY,40.7630,-73.8708,24.143.199.156 +US,MANNFORD,OK,36.0666,-96.3642,64.129.104.132 +DE,LAUF,BY,50.00,10.95,84.53.146.39 +RU,KLIMOVSK,"",61.28,53.63,80.239.237.93 +CZ,LOSAN,"",50.40,13.52,23.62.237.133 +DE,RADOLFZELL,BW,47.73,8.97,2.20.142.166 +IT,ANTEA,"",45.85,9.67,2.18.240.95 +CR,LIBERIA,"",10.63,-85.43,72.164.253.83 +US,ELIZABETHTON,TN,36.4118,-82.0968,184.29.107.20 +JP,SAGA,41,33.25,130.30,117.104.139.136 +US,BREVARD,NC,35.2304,-82.7632,184.51.35.226 +US,GALATIA,IL,37.8301,-88.6284,107.14.38.217 +US,GATECITY,VA,36.6668,-82.6167,64.86.201.121 +DE,DUREN,NW,50.80,6.48,23.14.94.228 +US,SHEBOYGANFALLS,WI,43.7266,-87.8486,184.85.215.165 +US,BUNKIE,LA,30.9328,-92.1876,96.17.153.157 +US,SAUKCITY,WI,43.2637,-89.8631,184.85.215.165 +IT,QUADRI,"",41.92,14.28,95.101.34.105 +BG,KAZANLAK,"",42.62,25.40,2.20.142.173 +IT,LADISPOLI,"",41.93,12.08,46.33.70.216 +PH,CAFE,"",15.32,120.70,58.71.107.120 +DE,KANZLEI,NW,51.25,6.68,80.157.170.158 +US,EASTROCHESTER,NY,43.1125,-77.4905,107.14.38.227 +IR,SHARIF,"",34.07,48.08,80.15.235.161 +FR,CANNES,"",43.55,7.02,2.16.117.200 +US,FRUITA,CO,39.2686,-108.68,63.235.21.147 +MT,SLIEMA,"",35.91,14.50,23.14.94.220 +US,HINCKLEY,OH,41.2388,-81.7346,107.14.38.224 +FR,RILLIEUX,"",45.82,4.90,90.84.50.115 +NL,LISSE,"",52.25,4.57,92.122.189.114 +DE,ENG,BY,48.85,12.80,80.157.170.231 +TH,KOH,"",18.82,101.05,180.180.251.220 +US,WORLAND,WY,43.9271,-107.8134,205.185.195.183 +US,OTISORCHARDS,WA,47.6956,-117.1108,67.131.104.14 +US,MIDDLEBORO,MA,41.8934,-70.9117,184.25.109.213 +US,MAUMEE,OH,41.5735,-83.6863,65.113.249.11 +US,MCRAE,GA,31.9833,-82.8682,63.216.54.229 +US,TRUMANN,AR,35.6187,-90.5393,173.197.194.159 +IN,NARAINA,RJ,26.78,75.20,96.17.182.130 +CZ,BORKOVANY,"",49.03,16.82,23.74.24.69 +FR,MONTARGIS,"",48.00,2.75,2.16.117.190 +CZ,HRADECKRALOVE,"",50.21,15.84,23.62.237.138 +SE,MALA,M,56.23,13.70,2.21.240.58 +DE,BENSHEIM,HE,49.68,8.62,77.67.27.250 +US,CASTLEHAYNE,NC,34.3390,-77.8941,184.27.45.150 +US,WOODSCROSS,UT,40.8888,-111.9281,23.61.195.165 +KR,ANSAN,"",37.32,126.82,61.111.58.43 +US,LAURINBURG,NC,34.7588,-79.4468,209.18.41.27 +JP,HACHIOJI,13,35.66,139.33,72.246.184.89 +US,MELVINDALE,MI,42.2809,-83.178,23.67.60.217 +US,KEENE,NH,42.9764,-72.2744,107.14.38.217 +US,NORTHMYRTLEBEACH,SC,33.8371,-78.6471,184.51.35.226 +US,CEDARBURG,WI,43.3081,-88.0364,65.113.249.8 +GB,SELLING,EN,51.27,0.92,77.67.27.235 +FR,SAINTJULIENENGENEVOIS,"",46.13,6.08,2.16.117.190 +FR,METZ,"",49.13,6.17,88.221.15.110 +US,HIGHSPRINGS,FL,29.8528,-82.6553,23.33.186.101 +US,JUNCTIONCITY,KS,38.9467,-96.7996,174.76.226.117 +US,MUNCY,PA,41.2250,-76.7388,63.216.54.236 +BR,NOVOHAMBURGO,RS,-29.68,-51.13,187.59.4.154 +IT,DESENZANODELGARDA,"",45.47,10.53,195.22.200.240 +US,BEALETON,VA,38.5752,-77.8213,23.192.161.21 +BR,ARACAJU,SE,-10.92,-37.07,200.216.8.59 +PL,CIECHOCINEK,"",52.87,18.80,80.239.222.190 +ID,BADUNG,"",-7.57,112.50,96.17.180.166 +JP,ISUZU,17,37.33,136.73,23.15.1.67 +ES,ARNEDO,"",42.22,-2.10,92.123.73.26 +US,VIVIAN,LA,32.8582,-93.9626,23.212.53.64 +US,SCOBEY,MT,48.7328,-105.3949,184.27.179.187 +FI,KUOPIO,"",62.90,27.68,193.184.164.238 +JP,TSUSHIMA,23,35.17,136.72,23.3.104.15 +US,WINAMAC,IN,41.0563,-86.6606,205.185.195.170 +PL,RADOM,"",51.42,21.15,95.101.2.112 +IR,GILAN,"",33.11,49.61,23.14.94.224 +NL,LEUR,"",51.82,5.70,92.122.189.114 +ME,CRNAGORA,"",43.22,19.01,23.14.94.214 +CF,BANGUI,"",4.37,18.58,95.101.34.105 +ID,SAMPIT,"",-2.53,112.95,23.0.162.21 +DE,KREISCHA,SN,51.28,13.10,195.95.193.147 +US,CAROLINABEACH,NC,34.0370,-77.9026,184.28.127.58 +MY,IPOH,"",4.58,101.08,63.233.61.159 +NL,NAALDWIJK,"",52.00,4.20,92.122.189.85 +PL,PODLASIE,"",51.93,17.95,2.22.52.109 +AT,MICHAEL,"",47.13,16.27,195.145.147.101 +US,LAVONIA,GA,34.4474,-83.1313,63.216.54.236 +US,RUSHVILLE,IN,39.6183,-85.4164,23.67.60.222 +IN,GULBARGA,KA,17.33,76.83,117.239.240.76 +US,ABERCROMBIE,ND,46.4479,-96.7302,23.79.255.153 +US,WENTZVILLE,MO,38.7993,-90.8471,204.93.47.220 +DE,PLAUEN,SN,50.50,12.13,80.157.150.192 +PL,GOSTYNIN,"",52.43,19.48,80.157.149.181 +EE,KURESSAARE,"",58.24,25.81,213.155.156.206 +RU,NADYM,"",65.53,72.52,92.122.215.89 +TR,ESKISEHIR,"",39.77,30.53,193.45.15.199 +DE,STRELITZ,MV,53.33,13.10,80.157.170.231 +FR,CREIL,"",49.27,2.48,2.16.117.190 +DE,NIEFERN,BW,48.92,8.78,23.14.94.220 +RU,UGRA,"",54.50,36.12,80.239.222.167 +US,STRATFORD,IA,42.2953,-93.8747,165.254.114.198 +US,BENNINGTON,VT,42.9148,-73.1152,107.14.38.217 +PH,LOPEZ,"",13.88,122.25,58.71.107.119 +JP,MATSUE,32,35.47,133.07,117.104.139.136 +US,SUGARGROVE,IL,41.7828,-88.4458,23.67.60.220 +CO,IPIALES,"",0.83,-77.62,200.14.44.103 +US,DELAFIELD,WI,43.0452,-88.3996,107.14.38.218 +NG,KANO,"",12.00,8.52,92.123.73.233 +FR,VAULXENVELIN,"",45.78,4.93,2.16.117.190 +MY,BADAK,"",6.48,100.57,203.106.85.4 +US,OLYMPICVALLEY,CA,38.9090,-121.0703,65.113.249.11 +SE,SKONDAL,AB,59.25,18.12,82.96.58.102 +US,BLANDON,PA,40.4457,-75.8746,165.254.48.154 +BE,LEUVEN,"",50.88,4.70,95.101.2.112 +US,IVYDALE,WV,38.5245,-81.029,23.74.8.8 +US,RAYNHAM,MA,41.9389,-71.0535,23.67.60.220 +US,HOPEWELL,VA,37.2760,-77.217,184.27.45.150 +US,APOLLOBEACH,FL,27.7623,-82.3865,192.204.82.221 +FR,CRETEIL,"",48.78,2.47,92.122.189.85 +DE,BIBERACH,BW,49.19,9.14,23.14.94.228 +PL,LESZNO,"",52.27,20.60,2.22.61.99 +YT,DZAOUDZI,"",-12.78,45.25,2.20.243.42 +RU,NIZHNIYNOVGOROD,"",56.33,44.00,217.212.227.25 +US,BOULDERCITY,NV,35.9098,-114.7587,165.254.144.32 +US,COLUMBIANA,OH,40.8786,-80.6854,23.192.161.16 +HN,SANPEDROSULA,"",15.50,-88.03,23.74.2.7 +US,BACLIFF,TX,29.5051,-94.9907,23.212.53.64 +RU,CHAPLYGIN,"",45.11,40.76,80.239.222.169 +CN,HENGYANG,HN,26.97,112.60,72.246.191.19 +US,GARRETTSVILLE,OH,41.3076,-81.0739,65.113.249.8 +DE,JULICH,NW,50.93,6.37,23.14.94.220 +US,MOORESTOWN,NJ,39.9782,-74.9415,184.26.44.42 +US,ROUNDHILL,VA,39.1007,-77.7961,96.6.47.106 +DE,MITTWALD,NW,52.38,8.63,92.122.207.179 +PL,GNIEZNO,"",52.55,17.60,23.14.94.228 +CN,WUXING,ZJ,30.87,120.10,72.246.191.16 +TR,ICEL,"",36.80,34.63,92.122.188.163 +FR,VIGNEUXSURSEINE,"",48.70,2.42,2.16.117.190 +US,CASSOPOLIS,MI,41.8990,-85.985,72.247.10.241 +IN,RAJPURA,PB,30.48,76.59,23.205.118.106 +ES,RIOJA,"",36.95,-2.45,92.122.188.163 +ID,PURWOKERTO,"",-7.42,109.23,23.0.162.46 +US,GRINNELL,IA,41.7319,-92.7662,23.74.8.24 +ES,ISLAS,"",43.37,-2.67,213.248.113.93 +US,MURPHYSBORO,IL,37.7760,-89.3234,23.74.8.24 +RU,BIZ,"",57.26,58.64,2.22.52.102 +FO,HOYVIK,"",62.03,-6.75,92.122.127.109 +FR,LETOUVET,"",45.35,5.95,2.16.117.200 +JP,MORI,22,34.83,137.93,23.15.1.29 +ID,LOMBOK,"",-8.50,116.67,23.0.162.21 +FR,ARGENTEUIL,"",48.95,2.25,2.16.117.190 +CN,SANYA,HI,18.24,109.50,184.50.87.176 +US,CORONADELMAR,CA,33.6005,-117.8539,184.50.26.204 +CH,DELEMONT,"",47.37,7.33,213.254.212.77 +US,WOODLAND,WA,45.9549,-122.6998,23.212.59.85 +RU,BALAKOVO,"",52.03,47.78,2.21.240.40 +FR,LAFRANCE,"",46.03,5.13,81.52.201.97 +DE,WADERN,SL,49.53,6.88,92.122.215.67 +US,LONGS,SC,33.8946,-78.7949,209.18.41.23 +US,ORANGEBEACH,AL,30.2789,-87.6082,72.246.247.30 +PK,MAIL,"",32.55,71.62,96.17.182.130 +US,HERINGTON,KS,38.7322,-97.0904,23.215.15.9 +PL,BIELANYWROCLAWSKIE,"",51.03,16.97,2.22.61.102 +FR,COLMAR,"",48.08,7.37,2.16.117.190 +CA,SAINTJEROME,QC,45.77,-74.00,67.69.197.160 +VN,HAIPHONG,"",20.87,106.68,23.76.205.111 +PL,INOWROCLAW,"",52.80,18.27,80.239.149.123 +CZ,PRIBRAM,"",49.70,14.02,23.62.237.135 +TR,GEBZE,"",40.80,29.42,79.140.94.183 +US,SANTAROSABEACH,FL,30.3512,-86.1547,184.51.35.215 +HU,PECS,"",46.08,18.23,80.239.237.231 +US,HUBERT,NC,34.6594,-77.2628,209.18.41.23 +NZ,KERIKERI,"",-35.22,173.97,219.88.186.167 +CZ,SVITAVKA,"",49.50,16.60,23.62.237.135 +UA,DNEPRODZERZHINSK,"",48.50,34.62,23.14.94.228 +PL,JASLO,"",49.75,21.47,2.22.52.105 +US,DEFUNIAKSPRINGS,FL,30.7313,-86.1987,184.51.35.226 +US,WHEELERSBURG,OH,38.7507,-82.7819,107.14.38.227 +US,WORTH,IL,41.6850,-87.7773,107.14.38.227 +US,PLATTECITY,MO,39.3588,-94.8136,209.170.117.169 +IN,NAVSARI,GJ,20.85,72.92,96.17.182.136 +AU,COFFSHARBOUR,NSW,-30.30,153.13,202.7.177.76 +US,COLLINS,MS,31.6692,-89.543,96.17.153.157 +DE,KNICK,NI,53.25,9.73,194.25.95.214 +US,BROWNSMILLS,NJ,39.9516,-74.5548,184.26.44.42 +NL,VEN,"",51.63,5.55,95.101.2.122 +RO,ORSOVA,"",46.75,24.90,81.196.26.236 +US,PROSSER,WA,46.3675,-119.7188,67.131.104.6 +TR,ESENTEPE,"",40.82,30.80,23.63.227.214 +US,SCHWENKSVILLE,PA,40.2583,-75.5011,23.67.242.156 +US,ROSCOE,IL,42.4315,-88.9848,184.85.215.165 +US,SOPHIA,WV,37.6919,-81.2784,184.28.17.55 +AU,HAWTHORN,VIC,-37.83,145.03,61.9.129.199 +US,BEGGS,OK,35.7942,-96.0408,173.197.194.166 +UA,RIVNE,"",48.25,31.75,2.22.52.102 +AT,REITH,"",48.10,15.63,195.145.147.109 +CZ,CESKEBUDEJOVICE,"",48.98,14.47,23.62.237.138 +SK,SURANY,"",48.08,18.18,23.62.237.133 +NZ,MIRAMAR,"",-41.32,174.82,184.28.126.8 +ID,PEKANBARU,"",0.53,101.45,124.155.222.130 +PL,KROSNO,"",51.17,19.68,80.157.149.129 +DE,EHRLICH,RP,50.70,7.75,23.14.94.228 +US,HARLEYSVILLE,PA,40.2685,-75.3957,184.26.44.42 +IT,MARCHE,"",45.90,11.90,193.45.15.198 +AT,AUEN,"",46.88,14.82,195.145.147.107 +DE,HELLWEG,NW,51.53,7.73,2.20.142.173 +ID,CAWANG,"",-6.25,106.87,23.0.162.46 +AT,ISCHGL,"",47.02,10.28,195.145.147.101 +US,TELLCITY,IN,38.0217,-86.7099,23.79.240.36 +SK,SNINA,"",48.98,22.15,23.62.237.137 +CA,LISTOWEL,ON,43.73,-80.97,72.246.43.233 +US,HAMPDEN,ME,44.7323,-68.9137,165.254.35.197 +US,HAPPYVALLEY,OR,45.4104,-122.5055,23.212.59.63 +HU,HARKANY,"",45.85,18.24,23.14.94.228 +VE,MARACAY,"",10.25,-67.60,72.246.65.26 +AQ,MCMURDO,"",-77.80,166.70,63.226.34.176 +US,SOMERSWORTH,NH,43.2536,-70.8856,23.192.161.16 +IN,KANGRA,HP,32.10,76.27,117.239.189.110 +US,DYER,IN,41.4630,-87.5082,107.14.38.217 +RO,SIMERIA,"",45.85,23.02,81.196.26.236 +PL,SWIETOCHLOWICE,"",50.28,18.92,2.22.52.102 +US,HAZELPARK,MI,42.4623,-83.0976,107.14.38.224 +US,ROCKISLAND,IL,41.4874,-90.5678,23.77.234.35 +UA,PERVOMAYSK,"",48.05,30.85,217.212.227.31 +PS,NABLUS,"",32.22,35.25,2.20.142.166 +US,BUZZARDSBAY,MA,41.7705,-70.5815,184.25.109.196 +TR,DUZCE,"",40.83,31.17,193.45.15.199 +US,ROMEO,MI,42.8454,-83.0393,23.67.60.217 +US,PICKWICKDAM,TN,35.0531,-88.2379,69.31.59.63 +US,NEBRASKACITY,NE,40.6534,-95.8738,107.14.43.29 +RU,VLADIMIRSKAYA,"",55.67,33.29,80.239.237.99 +NL,ZWOLLE,"",52.50,6.08,92.122.189.114 +US,LONGVALLEY,NJ,40.7842,-74.79,184.26.44.38 +AT,WAIDHOFENANDERYBBS,"",47.97,14.77,23.62.237.138 +FR,SAINTETIENNE,"",45.43,4.40,2.16.117.200 +FR,VALENCIENNES,"",50.35,3.53,2.16.117.200 +AT,SEEBODEN,"",46.82,13.49,195.145.147.107 +US,IRVINGTON,NJ,40.7242,-74.2319,23.67.242.139 +NL,HENGELO,"",52.27,6.80,92.122.189.114 +US,LEDGEWOOD,NJ,40.8749,-74.6666,72.247.10.241 +US,BRANFORD,CT,41.2857,-72.7978,184.25.109.200 +US,ARKADELPHIA,AR,34.0941,-93.0475,23.5.164.143 +JP,CHITOSE,01,42.82,141.65,72.246.184.89 +FI,LAUTTASAARI,"",60.16,24.87,82.96.58.85 +IT,SOLIGO,"",45.91,12.15,2.18.240.114 +JP,KAMAKURA,14,35.31,139.55,72.246.184.89 +AR,SANANDRES,"",-34.55,-58.53,80.239.237.231 +US,ANGLETON,TX,29.1898,-95.4754,96.17.163.165 +CA,CARP,ON,45.35,-76.03,67.231.211.247 +CN,MEIZHOU,GD,24.33,116.12,80.239.237.231 +US,PAGE,AZ,36.8282,-111.1539,65.116.149.89 +IN,ELURU,AP,16.70,81.10,124.124.201.221 +HT,DELMAS,"",18.54,-72.30,23.74.2.7 +US,THATCHER,AZ,32.7621,-109.8381,65.116.149.102 +CA,LAKELOUISE,AB,51.43,-116.18,24.244.17.197 +CN,KUITUN,XJ,44.42,85.00,80.239.237.230 +US,MONMOUTHJUNCTION,NJ,40.3897,-74.5487,124.155.222.130 +US,PEMBROKE,NC,34.6920,-79.1769,204.93.39.17 +US,SCOTTCITY,MO,37.1648,-89.4816,204.93.47.216 +US,LUCEDALE,MS,30.8443,-88.5703,96.17.153.162 +PL,MIROSLAW,"",52.53,19.82,2.22.52.101 +US,CHURCHVILLE,MD,39.5659,-76.2431,23.192.161.30 +IT,BARLASSINA,"",45.65,9.13,2.18.240.114 +US,COLBY,KS,39.3420,-101.0639,23.215.15.9 +TW,ILAN,"",24.77,121.75,60.199.191.59 +CZ,OSTRAVAZABREH,"",49.80,18.22,23.62.237.137 +EC,IBARRA,"",-0.30,-78.55,165.254.205.7 +US,LAKESAINTLOUIS,MO,38.7948,-90.7836,184.85.215.170 +DE,MEININGEN,TH,50.55,10.42,80.157.170.221 +RO,JIBOU,"",47.27,23.25,80.239.237.231 +VN,BINHAN,"",10.90,106.80,96.17.180.155 +US,WHITESULPHURSPRINGS,WV,37.8461,-80.2545,184.27.45.150 +NL,PIJNACKER,"",52.02,4.43,92.122.189.85 +US,MOBERLY,MO,39.4377,-92.3968,23.215.15.9 +US,SIBLEY,IA,43.4213,-95.7453,165.254.114.164 +US,WICKENBURG,AZ,33.9689,-112.7286,184.50.26.204 +CA,DAUPHIN,MB,51.15,-100.05,23.74.8.8 +PH,ZAMBOANGA,"",18.20,120.58,58.71.107.119 +US,BRONSTON,KY,36.8981,-84.635,80.239.237.230 +AU,EIGHTMILEPLAINS,QLD,-27.58,153.10,23.209.183.61 +US,NESCOPECK,PA,41.0389,-76.1727,165.254.48.150 +US,PEARLRIVER,LA,30.4339,-89.7967,96.17.153.157 +JP,SHINMACHI,06,38.40,140.38,72.246.184.92 +US,BENTLEYVILLE,PA,40.1179,-80.0044,184.28.17.76 +US,ASHLANDCITY,TN,36.2777,-87.0046,23.220.100.223 +IN,NAGPUR,MH,21.15,79.10,124.124.40.93 +IT,BERGAMO,"",45.68,9.72,195.22.200.221 +IN,JAMNAGAR,GJ,22.47,70.07,95.101.2.122 +US,SEDONA,AZ,34.6859,-111.2845,23.5.164.143 +NL,HOOFDDORP,"",52.30,4.70,92.122.189.85 +US,IOWAPARK,TX,33.9610,-98.717,107.14.36.200 +US,KIOWA,OK,34.7289,-95.9883,66.171.227.82 +PL,STAROGARDGDANSKI,"",53.97,18.55,2.22.52.101 +RU,KRASNOGORSK,"",55.83,37.33,80.239.222.169 +CH,BULLE,"",46.62,7.07,88.221.15.111 +IN,ALLAHABAD,UP,25.45,81.85,23.57.69.159 +LT,TAURAGE,"",55.25,22.28,92.122.189.85 +FR,HAMBACH,"",49.07,7.03,2.16.117.200 +FR,VEYREMONTON,"",45.68,3.17,2.16.117.200 +US,OTSEGO,MI,42.4993,-85.713,23.63.227.214 +FR,CERGY,"",49.03,2.07,2.16.117.200 +US,HOFFMANESTATES,IL,42.0425,-88.0794,23.67.242.156 +ES,SANTIAGODECOMPOSTELA,"",42.88,-8.55,2.20.44.111 +US,CLACKAMAS,OR,45.4104,-122.5055,23.212.59.63 +ES,MURCIA,"",37.98,-1.12,2.20.44.111 +KR,JEJU,"",33.51,126.52,61.111.58.229 +CN,LAIWU,SD,36.32,117.58,117.104.138.235 +DE,GUTERSLOH,NW,51.90,8.38,2.20.142.166 +CA,WHITECOURT,AB,54.13,-115.68,184.27.179.187 +RU,NOVATOR,"",60.74,46.21,213.155.156.212 +US,WOLCOTT,CT,41.6004,-72.9736,184.25.109.213 +US,SPRINGLAKE,MI,43.1035,-86.2217,23.63.227.227 +PL,WYSZKOW,"",52.60,21.47,80.157.149.129 +BT,MONGAR,"",27.25,91.20,23.76.205.111 +CN,LONGYAN,FJ,25.18,117.03,184.50.87.176 +CA,CHATEAUGUAY,QC,45.38,-73.75,67.69.197.92 +US,PRAIRIEVILLE,LA,30.3065,-90.9499,23.212.53.64 +TR,ERENKOY,"",40.97,29.07,77.67.29.109 +PL,KOSCIERZYNA,"",54.12,17.98,2.22.52.109 +IT,FERRERO,"",45.45,7.88,2.18.240.114 +US,MOSSLANDING,CA,36.7948,-121.7864,63.217.232.22 +US,CHESTERSPRINGS,PA,40.1084,-75.6462,184.26.44.38 +RU,NIZHNINOVGOROD,"",56.33,44.00,80.239.237.80 +CA,WINKLER,MB,49.18,-97.93,23.74.8.8 +PL,LOMZA,"",53.18,22.08,2.22.52.102 +US,HOLTSSUMMIT,MO,38.6152,-92.0964,209.170.117.178 +GB,MAYFAIR,EN,51.50,-0.15,195.245.125.107 +US,WESTHOLLYWOOD,CA,34.0942,-118.3815,165.254.144.25 +AU,FREMANTLE,WA,-32.05,115.77,23.62.224.28 +US,PRAIRIEDUCHIEN,WI,43.0613,-91.0624,23.67.60.217 +ES,LUGO,"",43.00,-7.57,80.149.168.109 +FR,LACOURNEUVE,"",48.92,2.38,2.16.117.190 +US,MOUNTMORRIS,MI,43.1205,-83.6765,23.67.60.223 +BR,MONTEAPRAZIVEL,SP,-20.75,-49.70,80.239.237.231 +FR,LANGUIDIC,"",47.83,-3.17,2.16.117.190 +DE,VELTEN,BB,52.68,13.18,213.248.108.244 +US,TIPTON,IN,40.2754,-86.0469,23.74.8.24 +TR,AFYON,"",38.75,30.55,80.239.237.231 +US,LUTCHER,LA,30.0539,-90.7041,96.17.153.157 +US,SEALBEACH,CA,33.7538,-118.0713,184.50.26.194 +CA,RIMOUSKI,QC,48.43,-68.52,184.27.120.65 +US,SYLVESTER,GA,31.5445,-83.898,63.141.200.241 +UA,MEGA,"",48.13,25.43,80.239.237.230 +US,BEMIDJI,MN,47.5271,-94.7611,63.151.29.15 +FR,LAROCHELLE,"",46.17,-1.15,2.16.117.200 +US,KAPLAN,LA,29.6422,-92.4232,23.79.240.36 +ES,SEVILLE,"",37.38,-5.99,80.239.237.231 +AT,WIESELBURG,"",48.13,15.13,195.145.147.107 +PL,WIELUN,"",52.98,20.03,2.22.52.102 +RU,KOGALYM,"",62.18,74.55,2.22.52.102 +PL,MALBORK,"",54.03,19.05,80.239.222.190 +RO,FILIASI,"",44.55,23.52,2.22.52.102 +BY,KIROVA,"",51.38,30.58,2.22.52.105 +IE,MULLINGAR,"",53.53,-7.35,88.221.222.33 +JP,MISAWA,02,40.68,141.40,72.246.184.81 +US,MARINETTE,WI,45.0728,-87.8197,107.14.38.224 +US,SILVERCITY,NM,33.0124,-108.2868,184.84.180.96 +FR,CHOLET,"",47.07,-0.88,2.16.117.200 +US,CROZET,VA,38.1379,-78.7036,184.27.45.157 +US,COLMAN,SD,43.9352,-96.8289,23.74.8.8 +US,NUTLEY,NJ,40.8192,-74.1574,23.67.242.156 +US,DANIA,FL,26.0519,-80.1424,184.28.184.16 +JP,KOWA,23,34.77,136.90,23.3.104.16 +BG,RAKOVSKI,"",42.30,24.97,2.20.142.166 +CA,WEYBURN,SK,49.67,-103.85,23.215.15.22 +PL,DZIERZONIOW,"",50.72,16.65,92.122.189.85 +ES,TOMELLOSO,"",39.17,-3.02,92.122.188.163 +US,PRINCESSANNE,MD,38.1954,-75.7083,209.48.37.183 +FR,SAINTPHILBERTDEGRANDLIEU,"",47.03,-1.63,81.52.201.82 +FR,MONTBELIARD,"",47.52,6.80,2.16.117.200 +DE,STRUTHHELMERSHOF,TH,50.75,10.50,77.67.27.235 +US,SOUTHOLD,NY,41.0609,-72.426,184.26.44.38 +PL,ZAWIERCIE,"",50.50,19.43,213.200.109.173 +CA,GATINEAU,QC,45.48,-75.65,67.69.197.92 +US,KERHONKSON,NY,41.7943,-74.3146,24.143.199.156 +US,PELLCITY,AL,33.5807,-86.3463,184.51.35.226 +CZ,NEUSTUPOV,"",49.62,14.70,2.20.142.166 +ES,FRANCO,"",42.72,-2.70,2.20.44.111 +RS,KOM,"",43.43,19.40,2.20.45.104 +IR,KORDESTAN,"",30.68,50.16,92.122.189.114 +US,HIGHRIDGE,MO,38.4787,-90.5323,96.17.14.16 +GB,FINCHLEY,EN,51.60,-0.17,23.67.255.158 +US,DIAMONDHEAD,MS,30.3820,-89.3694,92.122.188.163 +US,POQUOSON,VA,37.1315,-76.3584,204.2.243.143 +US,CHEVYCHASE,MD,38.9825,-77.0796,184.27.45.157 +UG,MAKERERE,"",0.33,32.57,195.245.125.114 +CZ,CHEB,"",50.07,12.37,23.74.24.69 +US,FALLSCITY,NE,40.1276,-95.5661,23.63.227.227 +IN,TIRUPPUR,TN,11.10,77.35,65.116.149.89 +US,CLARENDONHILLS,IL,41.7892,-87.957,23.67.60.222 +VN,LAI,"",15.77,107.72,23.5.165.167 +RS,DESPOTOVAC,"",44.09,21.45,23.62.237.138 +US,BEEVILLE,TX,28.4569,-97.768,184.26.93.111 +AU,ROCKDALE,NSW,-33.95,151.13,104.72.70.95 +AT,KLEDERING,"",48.13,16.43,23.74.24.66 +US,KIMBERLY,AL,33.7678,-86.8087,204.2.243.143 +US,EXPORT,PA,40.4280,-79.6049,184.26.44.42 +RU,LESNAYA,"",55.23,39.80,2.21.240.40 +JP,MAEBASHI,10,36.38,139.07,72.246.191.16 +SK,SENEC,"",48.22,17.40,23.14.94.228 +DE,KOCH,NW,51.17,6.33,23.212.108.28 +DE,BEIERSDORF,BY,50.28,10.93,2.20.142.166 +DE,RATINGEN,NW,51.30,6.85,2.16.217.206 +IN,SHIV,RJ,26.18,71.25,96.17.182.136 +FR,NEVERS,"",46.98,3.17,2.16.117.200 +US,FORTMITCHELL,KY,39.0279,-84.5635,184.51.147.6 +AT,FRITZ,"",47.53,15.87,23.62.237.137 +US,TALLASSEE,AL,32.5595,-85.8976,23.33.186.101 +HU,VARPALOTA,"",47.20,18.13,23.14.94.228 +TR,GAZIANTEP,"",37.08,37.37,23.74.24.69 +US,CHARLEROI,PA,40.1402,-79.9469,23.192.161.30 +AE,ALAIN,"",24.22,55.77,2.20.249.12 +US,FOSTORIA,OH,41.1667,-83.402,205.185.195.168 +US,MEADE,KS,37.2174,-100.3456,23.215.15.9 +US,GLOUCESTERPOINT,VA,37.2577,-76.4965,23.220.148.108 +US,WERNERSVILLE,PA,40.3472,-76.0868,23.192.161.21 +US,DAVIDSON,NC,35.4822,-80.8049,184.27.45.157 +AF,KHAN,"",33.60,70.08,79.140.94.183 +JP,SANYO,35,34.03,131.10,117.104.139.160 +MX,OAXACA,OAX,16.41,-96.63,107.14.43.30 +US,SAINTROBERT,MO,37.8445,-92.1463,209.170.117.178 +TR,SAKARYA,"",40.77,30.40,92.122.188.163 +FR,SAINTAIGNANGRANDLIEU,"",47.12,-1.63,2.16.117.200 +IT,FORLI,"",44.22,12.05,2.18.240.95 +US,HENNESSEY,OK,36.0641,-97.8809,174.76.226.110 +IT,SANSEVERINO,"",40.08,15.35,2.18.240.95 +AT,PERNITZ,"",47.90,15.97,195.145.147.101 +US,MARCUSHOOK,PA,39.8393,-75.4661,23.67.242.156 +JP,MIKATA,18,35.55,135.92,23.61.250.113 +KZ,TENGE,"",43.31,52.86,2.21.240.61 +RU,CHEREMKHOVO,"",60.73,30.50,2.21.240.61 +JP,KANUMA,09,36.55,139.73,23.3.104.16 +US,TOLLESON,AZ,33.1732,-112.3475,63.226.34.176 +DE,WEIHENSTEPHAN,BY,48.40,11.73,23.14.94.214 +RU,ENGELS,"",51.50,46.12,23.14.94.220 +US,CARBONCLIFF,IL,41.4962,-90.3857,165.254.134.201 +US,LANSDOWNE,PA,39.9372,-75.2636,23.67.242.156 +IN,BOLPUR,WB,23.67,87.72,23.57.76.18 +DE,BACKNANG,BW,48.95,9.43,194.25.95.225 +KZ,SEMIPALATINSK,"",50.41,80.23,23.14.94.224 +ID,PINANG,"",-6.22,106.67,23.0.162.40 +IN,SHRINAGAR,MP,22.95,79.52,96.17.182.130 +US,LARNED,KS,38.1779,-99.1746,23.215.15.22 +US,PORTWASHINGTON,WI,43.4225,-87.8809,65.113.249.8 +VN,BINHDUONG,"",15.85,108.38,165.254.1.165 +EC,BANOS,"",-1.40,-78.42,165.254.205.7 +US,WHITESTONE,NY,40.7862,-73.811,24.143.199.156 +DE,HILDEN,NW,51.17,6.93,23.14.94.224 +US,PINEBROOK,NJ,40.8673,-74.3427,184.26.44.42 +JP,OHORI,12,35.33,139.87,23.3.74.112 +PH,BINONDO,"",14.60,120.97,184.50.26.179 +MK,CAIR,"",42.02,21.44,195.145.147.101 +DE,WINTERBACH,RP,49.87,7.63,23.14.94.224 +PH,NOVALICHES,"",14.72,121.03,58.71.107.116 +US,PHILLIPS,WI,45.7439,-90.2959,23.74.8.24 +US,":{",NC,,, +AT,LENZING,"",47.97,13.62,84.53.146.35 +US,NATIONALCITY,CA,32.6702,-117.0918,23.216.10.78 +MX,TLAQUEPAQUE,JAL,20.65,-103.32,187.141.2.154 +US,AHOSKIE,NC,36.3091,-77.0137,209.18.41.23 +US,FRONTROYAL,VA,38.9572,-78.2104,184.26.44.40 +US,NEWHAMPTON,IA,43.0559,-92.3113,63.216.54.229 +ZM,KAFUE,"",-15.77,28.18,41.193.163.45 +DE,GIESEN,NI,52.20,9.90,80.157.150.192 +AR,MARCOSPAZ,"",-34.78,-58.85,23.74.2.12 +IN,KOLLAM,KL,11.45,75.68,117.239.240.96 +DE,BERKENTHIN,SH,53.73,10.65,92.122.207.179 +GB,HEMELHEMPSTEAD,EN,51.75,-0.47,23.212.108.8 +AU,FITZROY,VIC,-37.78,144.98,104.72.70.96 +FR,SATURARGUES,"",43.72,4.12,2.16.117.200 +GR,ARGOS,"",37.63,22.73,79.140.94.254 +PL,CHOJNOW,"",52.02,21.08,77.67.96.114 +TW,MIAOLI,"",24.57,120.82,61.220.62.175 +US,HOBBS,NM,32.6132,-103.3269,63.216.54.231 +IN,NAINITAL,UL,29.38,79.45,117.239.91.82 +RU,OREKHOVOZUEVO,"",55.82,38.98,213.155.156.206 +CZ,OBRANY,"",49.23,16.65,23.62.237.135 +PL,PONIATOWA,"",51.18,22.13,80.15.235.161 +DE,GOLDBACH,BY,49.99,9.19,23.14.94.214 +FR,SAINTLO,"",49.12,-1.08,2.16.117.200 +SE,SODERMALM,AB,59.32,18.08,213.155.156.206 +HU,SARVAR,"",47.25,16.93,23.62.237.138 +RU,NOVOROSSISK,"",44.72,37.77,2.21.240.61 +US,GAUTIER,MS,30.4104,-88.6488,24.143.197.189 +US,IMPERIALBEACH,CA,32.5734,-117.1175,23.220.149.124 +IT,PIAZZA,"",45.58,10.13,193.45.15.199 +US,CHEHALIS,WA,46.6561,-122.9934,67.131.104.6 +US,MARLIN,TX,31.3313,-96.8629,63.216.54.216 +US,WESTHARRISON,NY,41.0555,-73.7433,184.26.44.40 +US,BARBOURSVILLE,WV,38.3904,-82.2418,209.48.37.188 +US,NOWATA,OK,36.6745,-95.6917,63.235.21.141 +US,ELMIRAGE,AZ,33.5859,-112.3345,184.50.26.194 +IL,KINERET,"",32.71,35.57,212.143.162.162 +RO,BARLAD,"",46.23,27.67,81.196.26.198 +CZ,KLATOVY,"",49.40,13.30,23.62.237.133 +PL,ZIELONAGORA,"",51.70,19.70,2.22.52.101 +IN,PATAMATA,AP,16.48,80.65,23.205.118.106 +IT,MOZZATE,"",45.68,8.95,193.45.15.198 +FR,PANTIN,"",48.90,2.40,2.16.117.200 +RO,GIURGIU,"",43.88,25.97,88.221.93.150 +US,CRYSTALSPRINGS,MS,32.0027,-90.4734,65.113.249.8 +IN,MEERUT,UP,28.98,77.70,117.239.189.99 +CA,COBOURG,ON,43.97,-78.17,72.246.43.237 +DE,DIRLEWANG,BY,48.00,10.50,80.157.170.231 +US,STONYPOINT,NY,41.2394,-74.039,23.67.242.156 +DE,LIPPSTADT,NW,51.67,8.35,195.95.193.132 +HR,VARAZDIN,"",46.31,16.34,23.14.94.220 +FR,SURESNES,"",48.87,2.23,88.221.15.110 +KR,NAMSANDONG,"",37.72,126.50,23.14.94.214 +MY,SEPANG,"",2.70,101.75,58.26.185.125 +MX,MADERO,MIC,19.40,-101.27,187.210.208.101 +CN,LINCHENG,ZJ,30.93,119.79,117.103.188.205 +CZ,RUDOLTICE,"",49.70,14.60,2.16.217.211 +RO,MOLDOVANOUA,"",44.77,21.67,80.239.222.169 +AT,WILFERSDORF,"",48.27,16.10,46.33.70.97 +US,BUCHANAN,GA,33.8511,-85.2067,212.25.69.145 +PL,BRZESKO,"",49.97,20.62,80.239.222.167 +NO,KONGSVINGER,"",60.20,12.00,2.21.240.40 +RO,REGHIN,"",46.77,24.70,81.196.26.198 +US,MONONA,IA,43.0888,-91.4288,65.113.249.11 +JP,WASEDA,15,38.30,139.55,23.3.104.29 +PL,ZABKI,"",52.28,21.12,2.22.52.105 +RO,BISTRITA,"",45.18,24.05,81.196.26.237 +IN,KOLHAPUR,MH,16.70,74.22,117.239.189.111 +CA,MONTREALNORD,QC,45.60,-73.62,67.69.197.106 +CO,RIOHACHA,"",11.55,-72.92,190.90.221.149 +AU,MOONAH,TAS,-42.85,147.30,150.101.152.249 +US,WILLIAMSTON,NC,35.7282,-77.0495,23.5.164.143 +US,UNITY,ME,44.5885,-69.3433,23.212.53.64 +FR,SCHILTIGHEIM,"",48.60,7.75,2.16.117.190 +US,WAHPETON,ND,46.2654,-96.6056,63.216.54.236 +HU,VESZPREM,"",47.10,17.92,23.14.94.224 +FR,BELLEGARDESURVALSERINE,"",46.10,5.82,88.221.83.140 +CA,BROCKVILLE,ON,44.58,-75.68,23.79.255.153 +CA,VALCOURT,QC,45.48,-72.32,67.69.197.160 +US,WESTVILLE,IL,40.0417,-87.6306,204.93.47.220 +US,JESSUP,MD,39.1490,-76.7842,184.27.179.159 +NL,VORDEN,"",52.10,6.32,92.122.189.85 +IN,BHIMASHANKAR,MH,19.07,73.53,65.113.249.8 +IT,MAGNAGO,"",45.58,8.80,2.18.240.114 +ZA,RIVONIA,"",-26.05,28.05,41.193.163.53 +MK,SVETINIKOLE,"",41.87,21.94,23.74.24.69 +BE,NAMUR,"",50.47,4.87,23.62.100.152 +FR,GARGESLESGONESSE,"",48.97,2.42,2.16.117.200 +US,NEWBERRY,MI,46.4960,-85.4887,23.79.240.48 +AU,WAGGAWAGGA,NSW,-35.12,147.37,203.26.28.250 +AT,SOMMEREIN,"",47.98,16.65,195.145.147.108 +RU,SKALA,"",55.38,82.77,2.21.240.40 +US,LEESPORT,PA,40.4116,-75.999,184.26.44.38 +AT,STEYREGG,"",48.28,14.37,195.145.147.101 +IR,KISH,"",32.86,49.70,23.215.60.48 +JP,MOKA,09,36.43,140.02,72.246.191.16 +US,HIRAM,GA,33.8668,-84.7649,72.246.247.30 +MK,RADOVIS,"",41.64,22.46,95.101.34.109 +US,BREWER,ME,44.7782,-68.725,107.14.38.224 +SV,ANTIGUOCUSCATLAN,"",13.68,-89.23,23.33.186.101 +IN,GUWAHATI,AS,26.18,91.73,23.57.76.20 +US,DYERSVILLE,IA,42.4950,-91.1159,63.216.54.229 +FR,AULNAYSOUSBOIS,"",48.95,2.52,2.16.117.190 +US,COLLEGEPLACE,WA,46.0427,-118.4036,184.27.179.159 +JP,KINJO,12,35.92,139.88,72.246.191.16 +DE,NEUWIESE,SN,51.47,14.22,195.95.193.147 +TR,ANTEP,"",37.08,37.37,193.45.15.198 +IN,BODHGAYA,BR,24.70,84.98,23.205.118.109 +US,CAMPLEJEUNE,NC,34.7003,-77.3614,23.79.240.36 +US,MACEDONIA,OH,41.3152,-81.498,63.216.54.216 +SE,GALLIVARE,BD,67.13,20.70,80.239.237.80 +US,DELEON,TX,32.1142,-98.6051,23.212.53.64 +US,KINGSFORD,MI,45.8086,-88.101,72.246.247.30 +AT,NEUNKIRCHEN,"",47.72,16.08,23.74.24.69 +JP,YASHIMA,05,39.22,140.13,23.3.104.29 +IN,MACHILIPATNAM,AP,16.17,81.13,124.124.40.93 +PL,OSWIECIM,"",50.03,19.23,80.239.149.123 +AT,OEDT,"",48.75,15.48,84.53.146.37 +HU,MISEFA,"",46.80,16.98,195.145.147.109 +FR,HENINBEAUMONT,"",50.42,2.93,2.16.117.190 +TH,HATYAI,"",7.02,100.47,110.164.11.181 +PL,WIELOGLOWY,"",49.67,20.70,80.15.235.156 +PR,SANGERMAN,"",18.0846,-67.0463,204.2.243.135 +CN,FANYU,GD,23.12,113.25,184.84.239.175 +PL,MOSTOW,"",52.10,22.75,2.22.52.101 +AT,GASTHOF,"",47.43,13.38,46.33.70.104 +AR,MORENO,"",-34.46,-58.93,80.239.237.231 +PL,OSTROW,"",52.10,21.38,80.157.149.181 +AT,AXAMS,"",47.23,11.30,195.145.147.107 +US,SANDYHOOK,VA,37.7897,-77.9807,184.26.44.38 +AT,ERB,"",48.10,13.18,195.145.147.109 +US,CUTLER,CA,36.4976,-119.2842,63.217.8.169 +IR,ZAHEDAN,"",28.75,53.80,2.20.142.166 +PL,KWIDZYN,"",53.73,18.92,2.22.52.102 +US,THONOTOSASSA,FL,28.1050,-82.287,23.33.186.101 +PL,NIEPOLOMICE,"",50.03,20.23,80.15.235.156 +US,KENEDY,TX,28.7695,-97.8354,96.17.163.165 +RU,TOMARI,"",47.77,142.07,96.7.251.95 +UA,LISICHANSK,"",48.92,38.42,92.122.188.163 +CZ,MOST,"",50.53,13.65,23.74.24.69 +RO,MEDGIDIA,"",44.25,28.28,88.221.93.157 +BR,CERQUILHO,SP,-23.17,-47.74,92.122.188.163 +US,ATTICA,IN,40.2530,-87.1864,65.113.249.8 +BR,BRAGANCAPAULISTA,SP,-22.95,-46.57,200.174.107.42 +AT,KAPPL,"",47.52,10.47,195.145.147.108 +KR,JINJU,"",35.19,128.08,61.111.58.43 +IN,ULHASNAGAR,MH,19.22,73.15,213.248.108.244 +PL,NOWYSACZ,"",49.63,20.72,77.67.96.114 +BA,TRAVNIK,"",43.37,18.75,2.20.142.166 +AR,COMODORORIVADAVIA,"",-45.87,-67.50,190.98.167.230 +IN,CALICUT,KL,11.25,75.77,117.239.240.96 +US,LABELLE,FL,26.6279,-81.3332,23.79.240.36 +US,CASCADE,IA,42.2695,-91.0027,65.113.249.11 +RS,RUMA,"",45.01,19.82,23.62.237.135 +RU,BALASHIKHA,"",55.80,37.95,2.21.240.61 +PL,KOZIEGLOWY,"",51.77,21.00,2.22.52.101 +HR,VINKOVCI,"",45.29,18.80,46.33.70.104 +IN,ALIGARH,UP,27.45,83.13,184.25.157.169 +US,LENNON,MI,42.9989,-83.9455,23.74.8.8 +US,TONTOBASIN,AZ,33.8677,-111.3122,23.74.8.24 +US,POCAHONTAS,AR,36.3332,-91.0542,173.197.194.159 +RO,CAMPIATURZII,"",46.55,23.88,92.122.188.161 +HU,LAJOSMIZSE,"",47.02,19.55,23.62.237.138 +SK,ZVOLEN,"",48.58,19.13,23.62.237.133 +US,HAMLET,NC,34.8875,-79.6665,184.28.127.55 +ID,TEBET,"",-6.23,106.85,23.0.162.21 +RU,CHERNOGOLOVKA,"",56.00,38.37,92.122.188.163 +PL,ZALUSKI,"",52.17,20.93,80.239.222.190 +FR,POUILLYSOUSCHARLIEU,"",46.15,4.12,2.16.117.200 +BG,SHUMEN,"",43.27,26.92,2.20.142.166 +GR,SERRES,"",41.08,23.55,80.157.169.18 +US,ZAPATA,TX,26.8906,-99.1308,184.26.93.116 +RU,ELISTA,"",47.44,44.46,80.239.222.167 +US,HOMERVILLE,GA,31.0656,-82.7583,23.79.240.48 +BG,SILISTRA,"",44.12,27.27,23.14.94.228 +US,KATHLEEN,GA,32.4765,-83.6061,184.51.35.215 +PH,PARANAQUE,"",14.51,120.99,120.28.5.112 +CN,JINCHANG,GS,38.50,102.17,72.246.191.120 +IN,MADURAI,TN,9.93,78.12,92.122.188.163 +US,WALKERTOWN,NC,36.1899,-80.1591,209.18.41.23 +IL,HOLON,"",32.01,34.77,212.25.69.134 +US,GARFIELD,NJ,40.8788,-74.1075,23.67.242.139 +AR,GALVEZ,"",-33.03,-60.63,177.159.181.174 +DE,ED,BY,47.78,11.80,80.157.170.158 +RO,MOTRU,"",44.80,22.97,92.122.188.163 +DE,AALEN,BW,48.83,10.10,23.74.24.66 +DK,BORRIS,"",55.97,8.65,2.21.240.40 +US,MARYLANDHEIGHTS,MO,38.7275,-90.4524,204.93.47.216 +US,AMELIACOURTHOUSE,VA,37.3498,-77.9661,184.51.35.215 +DE,GRAS,BY,47.75,12.67,194.25.95.219 +US,PLAINSBORO,NJ,40.3338,-74.5836,184.26.44.42 +US,SILVERSPRINGS,NV,39.3955,-119.2669,23.61.195.165 +US,EASTHADDAM,CT,41.4660,-72.3865,184.25.109.196 +BG,SAMOKOV,"",42.33,23.55,93.186.137.231 +CZ,FRANTISEK,"",49.87,18.27,23.62.237.137 +AR,MARDELPLATA,"",-38.00,-57.55,190.98.167.230 +US,PORTDEPOSIT,MD,39.6245,-76.0756,65.121.209.127 +US,FORDYCE,AR,33.8659,-92.4841,23.74.8.8 +ID,SOLOK,"",-0.80,100.65,80.239.237.230 +FR,SASSETOTLEMAUCONDUIT,"",49.80,0.53,2.16.117.200 +US,LENOX,MA,42.3695,-73.2774,107.14.38.227 +US,BRUCE,WI,45.4985,-91.3289,23.74.8.24 +AT,PASCHING,"",48.25,14.20,23.62.237.138 +IN,DHARMAPURI,TN,12.13,78.17,23.205.118.106 +VE,LAGUAIRA,"",10.60,-66.93,23.74.2.7 +IL,EILAT,"",29.56,34.95,212.25.69.142 +IN,THANJAVUR,TN,10.80,79.15,117.239.240.96 +NZ,MOSGIEL,"",-45.88,170.35,184.28.126.7 +US,HANCOCK,MI,47.1715,-88.5503,65.113.249.11 +CH,GAMPELEN,"",47.02,7.05,193.247.167.211 +US,NORTHWOOD,OH,41.6045,-83.4717,65.113.249.11 +FR,VILLEFRANCHE,"",48.23,2.95,2.16.117.200 +CZ,PISEK,"",50.15,15.50,23.62.237.137 +BO,ORURO,"",-17.77,-67.48,72.246.65.37 +HR,SIBENIK,"",45.82,17.18,80.15.235.161 +EC,PASTAZA,"",0.04,-77.17,184.26.44.38 +RO,JILAVA,"",44.33,26.08,194.25.95.219 +DE,ROTHENBURG,BY,50.32,11.77,80.157.150.169 +US,TARRYTOWN,NY,41.0851,-73.846,23.79.255.149 +CA,TERREBONNE,QC,45.68,-73.63,67.69.197.92 +PL,ZDUNY,"",52.15,19.82,80.157.149.129 +US,LINN,MO,38.4764,-91.7793,23.63.227.227 +UA,VINNITSA,"",49.23,28.48,2.22.52.101 +CZ,VESELINADMORAVOU,"",48.95,17.40,92.122.188.163 +US,WAYZATA,MN,44.9781,-93.5263,23.67.60.223 +DE,BADHARZBURG,NI,51.88,10.57,92.122.207.179 +SE,KUNGSBACKA,N,57.48,12.07,2.21.240.40 +TH,RANGSIT,"",13.98,100.62,110.164.11.192 +NO,GRORUD,"",59.95,10.88,2.21.240.40 +US,NELSONVILLE,OH,39.4502,-82.2473,72.247.10.237 +RU,DOROZHNYY,"",59.22,39.88,2.21.240.40 +SE,KATRINEHOLM,D,59.00,16.20,213.155.156.212 +US,FITZGERALD,GA,31.7597,-83.2209,72.246.247.30 +GB,BUCKINGHAM,EN,52.00,-0.98,23.61.251.143 +DE,LEONBERG,BW,48.80,9.02,23.14.94.220 +US,FRUITLANDPARK,FL,28.8719,-81.9072,23.79.240.48 +US,NEAHBAY,WA,48.3685,-124.6238,165.254.1.165 +RU,OKHA,"",56.49,33.89,96.7.251.95 +FI,MARIEHAMN,"",60.10,19.95,2.21.240.40 +IN,KUKATPALLI,AP,17.48,78.42,117.239.240.96 +US,RIOLINDA,CA,38.6864,-121.4408,96.17.12.44 +GB,PADDINGTON,EN,51.50,-0.18,173.222.211.203 +US,NOKOMIS,FL,27.1186,-82.4447,23.79.240.36 +CH,HERISAU,"",47.40,9.27,213.254.212.102 +US,DILLSBURG,PA,40.0904,-77.0293,23.192.161.30 +DK,PADBORG,"",54.82,9.37,2.21.240.61 +US,LEMOYNE,PA,40.2478,-76.9006,23.192.161.21 +US,WRIGHTSVILLE,GA,32.7293,-82.7399,72.246.247.30 +CN,LOUDI,HN,27.75,111.98,72.246.191.19 +US,BRIDGMAN,MI,41.9364,-86.5496,23.67.60.223 +US,BETHPAGE,NY,40.7426,-73.4861,184.26.44.38 +US,EASTPOINTE,MI,42.4657,-82.946,23.63.227.227 +SI,ZRECE,"",46.38,15.37,194.25.95.214 +US,WICKLIFFE,OH,41.5969,-81.4651,107.14.38.218 +IN,SHILLONG,ML,25.58,91.87,124.124.40.93 +US,WELLSVILLE,NY,42.0803,-77.9333,107.14.38.217 +US,HAVELOCK,NC,34.8925,-76.9041,184.27.45.150 +TH,UTHAI,"",14.37,100.67,217.212.227.25 +TR,KAHRAMANMARAS,"",37.60,36.92,193.45.15.199 +KR,KARI,"",36.80,126.90,112.175.42.125 +US,ONAWA,IA,42.0513,-96.1326,165.254.207.117 +AU,BOTANY,NSW,-33.97,151.20,104.72.70.96 +IN,GUINDY,TN,13.01,80.22,23.205.118.109 +TW,HSINCHUANG,"",25.03,121.45,61.220.62.175 +US,KENTWOOD,LA,30.8810,-90.466,184.85.215.170 +US,PITMAN,NJ,39.7363,-75.1333,184.26.44.38 +AT,KAPFENBERG,"",47.43,15.30,2.16.217.211 +US,ALAMO,TX,26.2003,-98.1112,107.14.43.29 +US,ALTAVISTA,VA,37.1291,-79.2868,23.220.148.122 +US,STORMLAKE,IA,42.6740,-95.1635,23.63.227.214 +BE,KNOKKE,"",50.85,3.38,23.62.100.154 +JP,HYOGO,01,43.37,144.43,72.246.191.16 +KZ,SHKOLA,"",46.55,48.82,2.21.240.40 +US,GLADEWATER,TX,32.5672,-94.9346,23.5.164.143 +BG,DIMITROVGRAD,"",42.05,25.60,93.186.137.230 +TR,GAZI,"",38.25,35.47,23.14.94.214 +UA,DMITROVICH,"",49.77,23.35,92.122.215.89 +US,CUMBERLANDCENTER,ME,43.7981,-70.2656,107.14.38.218 +AT,ANIF,"",47.75,13.07,195.145.147.107 +US,WEAVERVILLE,NC,35.7234,-82.5239,184.27.45.150 +FR,MEY,"",49.13,6.23,23.200.87.58 +US,GEORGEWEST,TX,28.2189,-98.1396,184.25.157.162 +PH,FERNANDO,"",13.95,121.38,58.71.107.120 +JP,MITSUKE,22,34.72,137.87,23.3.104.29 +US,MILLRY,AL,31.6272,-88.354,184.51.35.226 +IT,LUCA,"",46.01,12.36,96.17.180.155 +US,BUHLER,KS,38.1245,-97.7604,23.215.15.22 +US,CLARENCE,NY,42.9851,-78.614,107.14.38.224 +US,MANISTEE,MI,44.1909,-86.1855,23.63.227.227 +US,CRYSTALRIVER,FL,28.9023,-82.5928,23.33.186.101 +IN,MOGA,PB,30.80,75.17,96.17.182.136 +PH,ROXAS,"",12.58,121.52,23.76.205.111 +CA,CHARLESBOURG,QC,46.87,-71.27,72.246.43.233 +NL,LEIDERDORP,"",52.15,4.53,92.122.189.85 +GB,ACCRINGTON,EN,53.77,-2.35,195.245.125.114 +SE,SOLLENTUNA,AB,59.42,17.95,213.155.156.212 +US,VIDALIA,GA,32.1357,-82.4052,72.246.247.5 +US,RANDALLSTOWN,MD,39.3744,-76.8156,184.27.45.150 +US,OLIVET,MI,42.4347,-84.8844,192.80.13.117 +US,HUDSONFALLS,NY,43.3537,-73.5472,23.67.242.139 +US,SCOTTSBLUFF,NE,41.9186,-103.6441,184.85.215.170 +US,NATCHEZ,MS,31.5340,-91.3231,96.17.153.157 +US,MILBANK,SD,45.1526,-96.6079,23.74.8.8 +RU,IM,"",52.82,138.33,72.246.184.81 +US,CLYDE,NC,35.6610,-82.9473,96.16.12.228 +US,GALAX,VA,36.6484,-80.9203,23.79.240.37 +JP,IKAWA,22,35.22,138.25,96.7.251.95 +US,LOCKHAVEN,PA,41.2558,-77.4987,184.28.17.55 +US,SHOEMAKERSVILLE,PA,40.4930,-75.9492,23.192.161.21 +IL,MAOZ,"",32.48,35.55,212.25.69.145 +US,FAIRBURY,NE,40.1696,-97.2152,184.26.93.111 +JO,FARAH,"",32.37,35.65,95.101.34.105 +US,LYNCHSTATION,VA,37.1483,-79.3585,184.29.107.38 +US,BERNALILLO,NM,35.4078,-106.8201,63.226.34.176 +GT,QUETZALTENANGO,"",14.83,-91.52,72.246.65.38 +ID,KARAWANG,"",-6.32,107.28,23.0.162.46 +US,FORESTHILL,MD,39.5864,-76.392,209.48.37.183 +CZ,KRALUPY,"",50.23,14.32,195.27.155.188 +DE,JESSEN,SN,51.18,13.28,23.14.94.214 +PR,MERCEDITA,"",18.1144,-66.8568,92.122.215.67 +CN,XUANCHENG,AH,30.95,118.76,72.246.191.19 +CA,TOFINO,BC,49.13,-125.90,24.244.17.197 +IN,MUZAFFARNAGAR,UP,29.47,77.68,23.205.118.106 +US,EMMITSBURG,MD,39.6880,-77.3321,72.247.10.237 +DE,WALDENBURG,BW,49.19,9.64,195.145.147.101 +IN,KOTTAYAM,KL,11.83,75.57,23.205.169.195 +US,WINDBER,PA,40.2054,-78.7856,23.192.161.21 +BR,JOAOPESSOA,PB,-7.12,-34.87,72.246.216.139 +AR,MAGDALENA,"",-35.07,-57.53,92.122.188.163 +IR,SHIRGAH,"",36.29,52.90,2.22.61.102 +SE,ASAKA,O,58.07,13.67,2.21.240.40 +ID,KEBALEN,"",-6.22,106.68,23.0.162.40 +US,BRAINTREE,MA,42.2036,-71.0017,72.247.10.241 +NL,URMOND,"",51.00,5.77,92.122.189.114 +AU,ALBURY,NSW,-36.08,146.92,60.254.143.211 +NL,APPINGEDAM,"",53.32,6.87,92.122.189.114 +DE,HILDESHEIM,NI,52.15,9.97,2.16.217.211 +RO,VULCAN,"",45.63,25.42,92.122.188.161 +NL,HEIDE,"",52.93,5.77,173.222.211.190 +IR,JAHROM,"",30.08,51.72,77.67.96.116 +US,HAROLD,KY,37.4843,-82.6492,23.63.227.214 +US,LOUDON,TN,35.7114,-84.3653,72.246.247.5 +US,BAYMINETTE,AL,30.8772,-87.7146,96.17.153.162 +RU,ARTEM,"",47.77,40.31,72.246.184.92 +RU,STUPINO,"",54.90,38.07,80.239.217.238 +US,SEATmidMileRTT,WA,,, +ES,BLANCA,"",38.18,-1.37,92.122.188.161 +DE,HAVIXBECK,NW,51.98,7.42,194.25.95.212 +US,MCFARLAND,WI,43.0035,-89.2832,184.85.215.170 +BY,KOBRYN,"",52.22,24.37,88.221.15.110 +FI,KEMI,"",65.73,24.57,193.184.164.219 +US,PITTSBORO,IN,39.8818,-86.4695,23.74.8.24 +UA,RODINSKOYE,"",48.35,37.20,92.122.188.163 +IN,WARDHA,MH,20.75,78.62,23.205.118.109 +AS,PAGOPAGO,"",-14.2702,-170.7003,184.28.126.8 +US,COOLIDGE,AZ,32.9772,-111.5231,184.50.26.179 +DK,ALBERTSLUND,"",55.65,12.35,213.155.156.207 +LV,AGENSKALNS,"",56.95,24.10,2.21.240.40 +DE,BRUCHSAL,BW,49.13,8.58,23.14.94.224 +PL,SIEDLCE,"",52.17,22.30,2.22.52.105 +BE,VILVOORDE,"",50.93,4.43,23.62.100.152 +US,MILLTOWN,WI,45.5218,-92.5019,23.63.227.227 +TR,ADIYAMAN,"",37.92,34.65,23.14.94.220 +FR,BOURGOGNE,"",49.35,4.07,81.52.201.82 +JP,WARABI,11,35.83,139.71,23.3.104.29 +US,NORTHSALTLAKE,UT,40.8433,-111.9231,96.17.180.155 +ID,SALATIGA,"",-7.32,110.50,23.0.162.54 +US,LEADVILLE,CO,39.2128,-106.3404,184.85.215.170 +RO,TECUCI,"",44.35,24.85,88.221.93.157 +US,SCOTCHPLAINS,NJ,40.6176,-74.3695,23.67.242.156 +PL,SOBOTKA,"",51.15,20.70,2.22.52.109 +RO,TULCEA,"",45.17,28.80,88.221.93.157 +IR,ABAD,"",32.56,51.90,96.17.182.136 +US,ROCKWELLCITY,IA,42.3850,-94.6304,184.27.120.50 +CO,YUMBO,"",3.58,-76.49,92.122.188.161 +RU,RUMYANTSEVO,"",55.63,37.43,2.21.240.61 +MG,TOAMASINA,"",-18.17,49.38,195.10.8.196 +FR,TOURLAVILLE,"",49.63,-1.57,2.16.117.200 +US,CANDOR,NY,42.2148,-76.3401,204.94.155.231 +IT,VAPRIODAGOGNA,"",45.60,8.55,2.18.240.95 +US,DANE,WI,43.2444,-89.5211,184.85.215.170 +US,WADESBORO,NC,35.0383,-80.0776,63.216.54.236 +RO,LUPENI,"",46.38,25.22,88.221.93.157 +TH,CHAIYAPHUM,"",15.80,102.03,180.180.251.220 +PL,PLOCK,"",52.55,19.70,80.239.222.169 +AT,STEYR,"",48.05,14.42,195.145.147.109 +US,WALBRIDGE,OH,41.5666,-83.5031,107.14.38.227 +US,NORTHADAMS,MA,42.6996,-73.0936,107.14.42.48 +FR,ROANNE,"",46.03,4.07,2.16.117.190 +US,NEWLONDON,NH,43.4164,-71.9863,165.254.35.182 +US,PORTCLINTON,OH,41.5070,-82.931,23.74.8.8 +PL,ZBOJNO,"",52.75,19.75,80.239.149.123 +US,NEWMAN,CA,37.2808,-121.2434,65.113.249.11 +NL,MEPPEL,"",52.70,6.20,92.122.189.114 +US,WOMELSDORF,PA,40.3905,-76.2083,23.192.161.21 +US,JAMISON,PA,40.2534,-75.0882,23.67.242.139 +US,WAMEGO,KS,39.2480,-96.3175,174.76.226.110 +CZ,KRENICE,"",50.03,14.67,23.62.237.133 +US,BETHEL,OH,38.9479,-84.0585,204.93.47.216 +US,HOLMES,PA,39.9003,-75.3086,184.27.45.150 +FR,PLANDECUQUES,"",43.35,5.47,2.16.117.200 +US,LEWES,DE,38.7339,-75.1733,23.192.161.16 +BR,PONTAGROSSA,PR,-25.08,-50.15,187.59.4.147 +FR,PONTDUCHATEAU,"",45.80,3.25,2.16.117.190 +TH,AYUDHYA,"",14.35,100.55,202.183.253.39 +US,SADDLEBROOK,NJ,40.9035,-74.0953,184.26.44.40 +DE,GARBSEN,NI,52.42,9.60,23.65.29.106 +PH,ANGELES,"",14.00,121.08,23.76.205.90 +CA,KINGCITY,ON,43.93,-79.53,72.246.43.232 +CZ,BYSTRICENADPERNSTEJNEM,"",49.52,16.27,23.62.237.138 +NO,RYGGE,"",59.38,10.72,82.96.58.85 +VN,HOANG,"",20.83,106.67,23.76.205.90 +US,DURAND,MI,42.9073,-83.9967,23.63.227.214 +JP,IRUMA,22,34.62,138.80,23.3.104.16 +RU,IRON,"",43.31,44.08,2.22.52.101 +DE,WOLFRATSHAUSEN,BY,47.92,11.42,195.145.147.101 +CA,NORTHBAY,ON,46.30,-79.45,92.122.189.85 +US,MCCOOK,NE,40.1761,-100.6468,23.215.15.32 +US,NEWEFFINGTON,SD,45.8778,-96.9166,23.79.255.153 +DE,BERGER,NW,51.72,7.50,194.25.95.212 +FR,SAINTSYMPHORIENDOZON,"",45.63,4.87,2.16.117.190 +FR,NOGENTSUROISE,"",49.27,2.47,2.16.117.190 +US,MIDDLEBURG,FL,30.0689,-81.8609,184.51.145.22 +SE,BORAS,O,57.72,12.92,23.65.29.106 +CN,CHENZHOU,HN,25.80,113.03,72.246.191.16 +CN,HUANGZHONG,QH,36.52,101.67,72.246.191.19 +US,UNIVERSITYCENTER,MI,43.5595,-83.9905,23.79.255.153 +US,BLOOMINGDALE,IL,41.9509,-88.0873,96.17.14.15 +JP,TSUYAMA,33,35.05,134.00,184.51.199.132 +KZ,PUSHKIN,"",50.29,73.79,80.239.237.80 +FI,TEUVA,"",62.48,21.73,193.184.164.239 +US,CAMBY,IN,39.6290,-86.3038,65.113.249.11 +US,MARNE,MI,43.0292,-85.8434,184.25.157.169 +BY,LOGOYSK,"",54.21,27.85,80.239.149.123 +US,VIRGINIA,MN,47.5233,-92.5364,23.77.234.35 +US,MOUNTRAINIER,MD,38.9430,-76.9649,23.192.161.16 +JP,UCHISAIWAICHO,13,35.67,139.75,72.246.184.89 +IN,BIHARSHARIF,BR,25.18,85.52,96.17.182.136 +DE,ILMENAU,TH,50.68,10.90,23.14.94.214 +AR,COLON,"",-33.89,-61.11,190.98.167.230 +AT,GROSSDORF,"",47.52,15.08,195.145.147.108 +RU,AVANGARD,"",54.47,37.12,80.239.237.93 +US,LEAVITTSBURG,OH,41.2542,-80.9112,107.14.38.227 +CN,CHENGMAI,HI,19.73,109.98,72.246.191.19 +PL,TARNOW,"",51.80,21.45,80.239.222.167 +US,GERING,NE,41.7826,-103.6811,184.85.215.165 +US,OSAGEBEACH,MO,38.1262,-92.6898,204.93.47.216 +US,VALLIANT,OK,33.9874,-95.0613,63.233.112.199 +US,CARMI,IL,38.0491,-88.1124,23.63.227.214 +DE,BADVILBEL,HE,50.18,8.75,194.25.95.214 +DE,UETZE,NI,52.47,10.20,23.14.94.220 +KR,SONGNAEDONG,"",37.53,127.12,125.56.214.149 +FR,BERGUES,"",50.03,3.72,2.16.117.190 +IN,VIRAMGAM,GJ,23.12,72.03,23.205.118.109 +US,CLARENDON,TX,35.0052,-100.8663,23.216.10.78 +CN,ZHENJIANG,JS,32.21,119.43,72.246.191.19 +PL,MIELEC,"",50.28,21.42,80.239.149.123 +RO,SIGHISOARA,"",46.22,24.80,92.122.188.161 +CH,FRIBOURG,"",46.80,7.15,213.254.212.98 +US,RAWLINS,WY,41.7532,-107.3722,23.61.195.163 +US,BELLEFOURCHE,SD,44.9293,-103.7531,23.63.227.227 +US,WINTERS,CA,38.5603,-121.9994,165.254.96.242 +AU,NORTHCOTE,VIC,-37.77,145.00,150.101.152.249 +RU,SMIRNYKH,"",49.75,142.83,72.246.184.84 +US,RONCEVERTE,WV,37.7253,-80.4371,184.27.45.157 +CZ,HUSTOPECE,"",48.93,16.73,23.74.24.66 +ID,KEMANG,"",-6.27,106.80,23.0.162.46 +US,CLEELUM,WA,47.3367,-121.0238,67.131.104.6 +US,PAWPAW,MI,42.2414,-85.9105,23.74.8.24 +BO,TARIJA,"",-19.49,-65.33,23.74.2.12 +CZ,JABLUNKOV,"",49.58,18.77,23.62.237.138 +US,ELBURN,IL,41.8654,-88.4653,23.67.60.222 +DE,ZWICKAU,SN,50.73,12.50,23.14.94.220 +RU,NOVOMOSKOVSK,"",54.09,38.22,92.122.188.163 +NL,VEENENDAAL,"",52.03,5.55,92.122.189.85 +DE,CUNEWALDE,SN,51.10,14.52,195.95.193.132 +FR,PONTCHATEAU,"",47.43,-2.08,2.16.117.190 +US,TUOLUMNE,CA,37.9468,-120.25,23.61.195.163 +DE,FAHNEN,NW,51.60,8.02,80.157.150.197 +VN,BA,"",21.30,106.50,23.76.205.111 +DE,ROTTENBURG,BW,48.47,8.93,23.14.94.224 +DK,ALLER,"",55.35,9.53,23.65.29.93 +US,ORADELL,NJ,40.9548,-74.0328,23.67.242.139 +CC,BANTAMVILLAGE,"",-12.12,96.88,96.17.180.166 +SE,SKANE,S,59.48,13.33,72.246.43.233 +JP,KITA,13,26.72,142.12,23.3.104.15 +US,OLDHICKORY,TN,36.2447,-86.616,23.79.240.36 +US,FOREST,MS,32.2901,-89.4443,165.254.138.175 +US,WILLIS,TX,30.4477,-95.5183,204.2.223.91 +US,VALLEYSTREAM,NY,40.6745,-73.7041,184.26.44.38 +RO,SFANTUGHEORGHE,"",44.65,26.83,2.22.52.101 +CZ,UHERSKYBROD,"",49.03,17.65,23.62.237.133 +US,EASTALTON,IL,38.8713,-90.0443,96.17.14.15 +CH,MASSAGNO,"",46.02,8.95,194.25.95.212 +CZ,OLBRAMKOSTEL,"",48.92,15.95,23.62.237.133 +DE,BROICH,NW,50.85,7.23,77.67.27.235 +RU,DOMODEDOVO,"",55.46,37.70,80.239.217.238 +FR,TOURCOING,"",50.72,3.15,2.16.117.185 +US,DIAMONDVILLE,WY,41.7777,-110.5371,23.212.53.75 +ES,ALORA,"",36.80,-4.70,2.20.44.111 +CH,URTENEN,"",47.03,7.48,193.247.167.211 +DZ,ANNABA,"",36.90,7.77,79.140.94.234 +TW,PANCHIAO,"",25.02,121.45,92.122.188.161 +PR,LARES,"",18.2912,-66.8528,72.246.65.26 +US,CENTRAL,SC,34.7453,-82.8049,23.79.240.36 +US,NEGAUNEE,MI,46.4658,-87.5578,184.85.215.170 +US,COCHRANE,WI,44.2495,-91.8243,23.63.227.227 +IT,VEROLI,"",41.68,13.42,193.45.15.198 +VN,CHITHANH,"",13.30,109.22,23.76.205.90 +IN,BELLARY,KA,15.15,76.93,23.205.118.106 +US,SUMMIT,MS,31.2993,-90.4958,72.246.247.30 +FI,LAHTI,"",60.97,25.67,82.96.58.102 +JP,TAGAWA,06,38.68,139.75,210.175.5.183 +CH,LOSTORF,"",47.38,7.95,193.247.167.214 +RU,LUCHEGORSK,"",46.48,134.20,72.246.184.84 +SE,SANDVIK,AB,59.35,17.98,23.62.100.152 +US,HARRISONCITY,PA,40.3834,-79.6667,23.192.161.21 +GB,CHORLEY,EN,53.65,-2.62,92.122.54.12 +FR,ALES,"",44.85,0.87,2.16.117.190 +UA,BROVARY,"",50.50,30.77,217.212.227.25 +MK,VELES,"",41.72,21.78,23.62.237.133 +DE,ASCHAFFENBURG,BY,49.97,9.15,23.14.94.224 +DE,TAUCHA,ST,51.20,12.08,80.157.150.197 +AR,QUILMES,"",-34.72,-58.27,92.122.188.161 +DE,DETTINGENANDERERMS,BW,48.53,9.35,84.53.146.39 +PL,ODRA,"",49.98,18.33,2.22.52.102 +US,NETCONG,NJ,40.8970,-74.7002,23.76.205.111 +DE,WECHLOY,NI,53.15,8.13,194.25.95.225 +CH,STEFFISBURG,"",46.78,7.63,193.247.167.214 +FR,SAINTJUSTENCHAUSSEE,"",49.50,2.43,2.16.117.190 +TZ,MOSHI,"",-3.35,37.33,23.212.108.8 +NL,VENLO,"",51.37,6.17,2.16.153.173 +US,SHALIMAR,FL,30.4411,-86.568,23.215.15.22 +US,BOSCOBEL,WI,43.1080,-90.6617,165.254.207.111 +US,REDSPRINGS,NC,34.7995,-79.1524,184.51.35.226 +BJ,SA,"",11.17,3.07,23.62.100.152 +US,BELFORD,NJ,40.4200,-74.0847,23.67.242.139 +DE,POHL,RP,50.25,7.87,23.74.24.66 +DE,ITZEHOE,SH,53.92,9.52,80.157.170.154 +US,PALA,CA,33.3876,-117.0743,65.113.249.8 +FR,CARPIQUET,"",49.18,-0.45,2.16.117.197 +UA,ZAPOROZHYE,"",47.60,33.40,92.122.188.161 +DE,MOELLN,SH,53.63,10.68,92.122.207.164 +US,PARKFOREST,IL,41.4594,-87.6908,23.67.60.223 +TZ,ZANZIBAR,"",-6.17,39.18,194.221.66.90 +IT,PARMA,"",44.80,10.33,2.18.240.114 +US,ROANOKERAPIDS,NC,36.4196,-77.714,23.79.240.48 +KR,GWANGJU,"",35.15,126.92,125.56.214.166 +NO,ROROS,"",62.58,11.40,213.155.156.212 +SE,LANDSKRONA,M,55.87,12.83,213.155.156.212 +FR,FAULQUEMONT,"",49.05,6.60,23.74.24.66 +SE,MOTALA,E,58.55,15.05,2.21.240.40 +US,SAINTLEO,FL,28.3162,-82.2455,72.164.253.83 +GB,PONTYPRIDD,WA,51.60,-3.33,23.61.251.145 +NL,BENTHUIZEN,"",52.08,4.55,23.62.100.152 +DE,FARMSEN,NI,52.17,10.10,80.157.150.201 +RU,KYZYL,"",53.78,55.25,2.21.240.61 +AT,UNTERHATZENDORF,"",46.97,16.02,195.145.147.107 +US,BROOKLET,GA,32.2794,-81.623,184.51.35.226 +MY,TASEK,"",4.65,101.12,203.106.85.4 +DE,WILSDRUFF,SN,51.05,13.53,195.95.193.132 +FR,PRA,"",45.83,5.85,23.200.87.58 +US,MAUSTON,WI,43.7786,-90.0517,23.74.8.8 +US,CLEARLAKE,IA,43.1769,-93.3674,65.113.249.11 +CA,PORTAGELAPRAIRIE,MB,49.97,-98.30,23.74.8.24 +FR,MENTON,"",43.78,7.50,2.16.117.197 +FR,DEUILLABARRE,"",48.98,2.33,2.16.117.197 +US,HAWKINSVILLE,GA,32.2568,-83.5362,184.51.35.226 +IE,MALLOW,"",52.13,-8.63,88.221.222.33 +US,NEWMARTINSVILLE,WV,39.6454,-80.8449,184.27.45.157 +FR,BONNEVILLE,"",48.55,2.28,2.16.117.185 +ID,TEGAL,"",-6.87,109.13,23.0.162.54 +US,HALLSVILLE,TX,32.4986,-94.513,23.215.15.9 +IN,JAUNPUR,UP,25.73,82.68,96.17.182.127 +US,TUBAC,AZ,31.6092,-111.0466,65.113.249.8 +US,CASEY,IL,39.3139,-87.9965,23.74.8.8 +HU,DUNAPATAJ,"",46.63,19.00,23.62.237.138 +DE,NEUSTADTBEICOBURG,BY,50.32,11.12,84.53.146.39 +CN,YUEYANG,HN,29.38,113.10,72.246.191.16 +CZ,MALES,"",50.30,13.18,23.74.24.66 +US,FORTRICHARDSON,AK,61.2265,-149.6208,23.212.59.63 +RU,PEROVO,"",55.73,37.77,217.212.227.31 +IN,RANCHI,JH,23.35,85.33,92.122.188.161 +US,RAYVILLE,LA,32.4475,-91.7992,72.246.247.5 +DE,ESSLINGEN,BW,48.75,9.30,84.53.146.39 +US,EASTQUOGUE,NY,40.8496,-72.6007,184.26.44.42 +IT,MODENA,"",44.67,10.92,195.22.200.221 +PL,JAKTOROW,"",52.08,20.57,80.157.149.181 +US,MOFFAT,CO,37.9777,-105.7795,64.145.95.126 +BA,ZAVIDOVICI,"",44.45,18.15,23.62.237.133 +US,SERGEANTBLUFF,IA,42.3991,-96.3551,165.254.207.117 +BR,BARRETOS,SP,-20.55,-48.55,177.159.174.13 +ID,CIKARANG,"",-6.25,107.15,23.0.162.21 +PL,PARCZEW,"",51.63,22.90,80.15.235.163 +US,CORTLANDTMANOR,NY,41.2893,-73.9009,184.26.44.38 +DK,VIBY,"",55.55,12.03,23.65.29.106 +RO,CAMPINA,"",45.13,25.73,88.221.93.157 +SI,KAMNIK,"",45.95,14.42,2.20.142.166 +DE,APOLDA,TH,51.02,11.50,92.122.207.179 +US,TWORIVERS,WI,44.2198,-87.5999,184.85.215.170 +SE,SAVSJO,F,57.40,14.67,107.14.32.228 +DE,NEUBURG,RP,48.98,8.25,2.22.61.102 +RO,BUFTEA,"",44.57,25.95,2.22.52.105 +GB,KEELE,EN,53.00,-2.28,88.221.87.112 +BG,SIMITLI,"",41.88,23.12,93.186.137.231 +US,FOUNTAININN,SC,34.6459,-82.2156,165.254.138.175 +AT,NEUSTADT,"",48.03,16.78,195.145.147.109 +IR,BUSHEHR,"",28.97,50.83,213.200.109.173 +US,FULTONDALE,AL,33.6060,-86.8244,184.28.127.55 +BE,KORTRIJK,"",50.83,3.27,23.62.100.152 +US,KENLY,NC,35.6072,-78.1393,23.79.240.37 +DE,FREIBERG,SN,50.92,13.37,84.53.146.35 +JP,SHIBUYA,13,35.66,139.70,72.246.184.89 +PH,BACOLOD,"",10.67,122.95,58.71.107.116 +US,ELMONT,NY,40.7013,-73.7074,184.26.44.42 +PL,SKIERNIEWICE,"",51.97,20.15,2.22.52.109 +NP,POKHARA,"",28.23,83.98,23.76.205.111 +MK,BITOLA,"",41.03,21.34,23.62.237.138 +US,HANCEVILLE,AL,34.0311,-86.8105,72.246.247.30 +US,GUYTON,GA,32.3167,-81.3986,184.51.35.215 +TH,HONG,"",18.43,99.45,92.122.188.161 +CH,RHEINFELDEN,"",47.55,7.78,23.14.94.228 +US,JEROME,ID,42.7238,-114.3385,67.131.104.14 +US,HINESVILLE,GA,31.8475,-81.5964,23.79.240.48 +IR,IRANSHAHR,"",28.95,58.88,107.14.32.228 +NZ,GISBORNE,"",-38.65,178.00,203.96.118.165 +US,IMMOKALEE,FL,26.3154,-81.2708,23.215.15.9 +US,JOPPA,MD,39.4408,-76.3547,184.27.45.157 +US,OLDWESTBURY,NY,40.7854,-73.596,184.26.44.38 +US,DALHART,TX,36.2600,-102.5337,23.215.15.22 +DE,ANSBACH,BY,49.30,10.58,80.157.150.192 +AT,DRAU,"",46.58,14.00,195.145.147.101 +DE,TORGELOW,BB,52.75,13.97,195.145.147.108 +JP,TOYOHASHI,23,34.77,137.38,23.61.250.108 +JP,KUROSAWA,20,35.85,137.63,23.15.1.67 +RU,ZVEREVA,"",46.10,47.70,213.155.156.212 +US,SOUTHWILLIAMSON,KY,37.6621,-82.2917,184.28.17.55 +FI,HYVINKAA,"",60.63,24.87,184.150.187.108 +IT,SANVINCENZO,"",43.10,10.53,2.18.240.114 +US,ELDRIDGE,IA,41.6660,-90.5607,23.79.240.47 +US,WISCONSINDELLS,WI,43.6772,-89.746,23.63.227.227 +US,COBLESKILL,NY,42.6995,-74.5108,165.254.48.155 +CN,CHUNAN,ZJ,29.60,119.02,72.246.191.16 +RO,TOPLITA,"",45.05,24.77,92.122.188.161 +US,HILLSIDE,NJ,40.6961,-74.2294,184.26.44.40 +US,BIDDEFORD,ME,43.4906,-70.5283,165.254.48.155 +US,HARRODSBURG,KY,37.7856,-84.8966,209.18.46.205 +US,PORTOLA,CA,39.8755,-120.4492,63.233.61.159 +US,PETOSKEY,MI,45.3433,-84.8827,96.17.180.177 +US,SHAWAFB,SC,33.9749,-80.463,209.18.41.27 +RO,TARNAVENI,"",46.33,24.28,77.67.27.250 +AT,HEILIGENKREUZ,"",48.05,16.13,195.145.147.101 +US,AFTON,WY,42.6962,-110.9188,173.223.52.70 +US,THOMPSONSSTATION,TN,35.8120,-86.9532,23.79.240.36 +JP,NISHINO,04,38.63,141.20,23.3.74.112 +TH,KONG,"",16.93,99.97,23.14.94.228 +CH,FLIMS,"",46.83,9.28,193.247.167.211 +US,CHAGRINFALLS,OH,41.4475,-81.4018,107.14.38.224 +US,SMARTT,TN,35.6544,-85.8274,23.79.240.37 +DE,LOHNE,HE,51.18,9.27,92.122.207.179 +CH,MONTHEY,"",46.25,6.95,92.122.189.85 +US,SHIPPENSBURG,PA,40.0414,-77.4967,205.185.195.170 +AT,HUBEN,"",46.93,12.57,195.145.147.107 +FR,AUBIGNY,"",48.60,2.68,2.16.117.197 +FR,SAINTMEDARDENJALLES,"",44.90,-0.73,2.16.117.212 +JP,MAKINO,27,34.35,135.28,72.246.184.84 +FR,CAMBRIN,"",50.50,2.73,2.16.117.212 +CZ,MEZIBORI,"",50.62,13.60,23.74.24.66 +IR,PARDIS,"",30.28,48.47,213.155.156.208 +IR,SABZ,"",37.43,47.82,96.17.182.136 +DK,VEJEN,"",55.48,9.15,2.21.240.40 +US,SPENCERPORT,NY,43.1672,-77.8292,23.74.8.24 +US,HICKORYHILLS,IL,41.7253,-87.8309,23.67.60.220 +RU,MICHURINSKIY,"",53.27,34.23,80.239.222.167 +US,BRADDOCK,PA,40.4039,-79.8613,184.28.17.55 +FR,BELLEY,"",48.30,4.15,2.16.117.185 +US,VILLANOVA,PA,40.0374,-75.3509,23.67.242.139 +US,WAUCHULA,FL,27.5499,-81.8315,23.33.186.134 +KZ,USHARAL,"",44.23,76.85,2.21.240.61 +CZ,PECKY,"",50.09,15.03,195.27.155.193 +DE,WOLF,HE,50.32,9.08,80.157.170.154 +DE,NORDHAUSEN,BW,49.10,9.11,195.95.193.132 +UA,ZHYTOMYR,"",50.25,28.67,23.14.94.214 +US,IJAMSVILLE,MD,39.3307,-77.3133,23.192.161.21 +US,FRIDAYHARBOR,WA,48.5377,-123.0836,23.212.59.85 +JP,NIKKO,09,36.75,139.62,96.7.251.95 +IN,VELLORE,TN,12.93,79.13,23.205.118.106 +AU,TUGGERANONG,ACT,-35.43,149.15,104.72.70.96 +US,MOUNTZION,IL,39.7516,-88.8516,23.67.60.220 +US,OLDORCHARDBEACH,ME,43.5280,-70.3929,107.14.38.218 +US,CLINTONVILLE,WI,44.6424,-88.7405,184.85.215.165 +RO,POPESTILEORDENI,"",44.38,26.17,81.196.26.198 +FR,PONTCHARRA,"",45.87,4.48,2.16.117.212 +NO,ALESUND,"",62.47,6.15,217.212.227.31 +US,COLLINGSWOOD,NJ,39.9152,-75.0615,184.26.44.42 +US,RICHTONPARK,IL,41.4788,-87.7394,23.67.60.222 +US,OSAWATOMIE,KS,38.4532,-94.9928,69.31.59.63 +IN,PUSA,BR,25.98,85.68,213.248.108.233 +US,ROSENBERG,TX,29.5301,-95.8155,23.215.15.22 +BR,JURUENA,MT,-12.85,-58.93,200.174.107.50 +FR,REALMONT,"",43.78,2.20,2.16.117.212 +US,PERRYHALL,MD,39.4067,-76.447,184.28.17.76 +IT,ROMANO,"",45.38,7.87,46.33.73.209 +FR,GOUSSAINVILLE,"",49.02,2.47,2.16.117.185 +BE,WAVER,"",50.93,4.10,23.62.100.154 +CA,PORTCOQUITLAM,BC,49.27,-122.78,96.17.180.166 +DE,HEIDENHEIM,BY,49.02,10.75,23.74.24.69 +US,WAPAKONETA,OH,40.5656,-84.1367,107.14.32.228 +CH,AARAU,"",47.38,8.05,88.221.93.150 +FR,CRE,"",47.68,-0.15,23.200.87.58 +PH,TACLOBAN,"",11.25,125.00,202.78.83.170 +DE,HOLTER,NW,51.77,8.12,195.145.147.108 +DO,BONAO,"",18.93,-70.42,72.246.65.38 +IN,REWA,MP,24.53,81.30,23.205.118.109 +US,BROWNSBORO,AL,34.7068,-86.4742,23.220.100.223 +BR,JANDIRA,SP,-23.52,-46.90,187.59.4.154 +TR,KARTAL,"",39.82,35.65,80.15.235.148 +US,NORTHPROVIDENCE,RI,41.8539,-71.4734,72.247.10.241 +US,NORTHVERSAILLES,PA,40.3802,-79.8167,23.192.161.21 +US,BRADLEY,CA,35.8301,-120.9932,23.215.15.22 +US,BLOOMER,WI,45.1062,-91.4948,23.63.227.214 +US,TELFORD,PA,40.3260,-75.3739,184.26.44.42 +AT,RANKWEIL,"",47.28,9.65,2.16.217.206 +DE,RHEINE,NW,52.28,7.45,2.22.61.102 +DE,BODEN,RP,50.47,7.85,92.122.215.89 +US,FORTWASHINGTON,PA,40.1333,-75.2109,96.17.180.166 +PL,JAWOROWA,"",52.13,20.95,80.157.149.181 +US,DEERLODGE,MT,46.3570,-112.7713,23.63.227.214 +CZ,DLOUHA,"",50.18,13.03,195.27.155.193 +US,LOUISA,KY,37.9848,-82.5857,184.28.17.76 +AR,SANTALUCIA,"",-33.87,-59.87,200.123.194.62 +IN,SOLAN,HP,30.92,77.12,96.17.182.127 +US,DANSVILLE,NY,42.5670,-77.738,107.14.38.227 +CN,SONGJIANG,SH,31.01,121.23,72.246.191.19 +AR,INGENIEROLUIGGI,"",-35.42,-64.48,200.123.201.219 +US,CENTERTON,AR,36.3689,-94.3208,23.215.15.22 +PH,MALACANANG,"",11.40,122.05,58.71.107.119 +US,MALTA,IL,41.8958,-88.8827,23.67.60.223 +FR,RAMONVILLESAINTAGNE,"",43.55,1.47,81.52.201.101 +IN,PAREL,MH,19.00,72.83,124.124.252.160 +RU,OR,"",51.20,58.70,80.239.222.167 +FR,CHEVRIERES,"",49.35,2.68,2.16.117.212 +NG,UYO,"",5.05,7.93,2.20.44.118 +JP,KANI,21,35.43,137.07,23.3.104.20 +US,RAYMOND,MS,32.2288,-90.4476,23.212.53.64 +ID,SENAYAN,"",-6.23,106.78,96.17.180.155 +RU,MIRNY,"",45.55,38.91,213.155.156.207 +AT,GROSSPETERSDORF,"",47.23,16.32,195.145.147.107 +AR,ALEJANDROKORN,"",-34.98,-58.38,190.98.167.230 +UA,IVANOV,"",49.48,28.35,46.33.70.97 +US,EPHRAIM,UT,39.3528,-111.5432,23.216.10.78 +AT,RANNERSDORF,"",48.12,16.47,195.145.147.107 +JP,KAWASAKI,14,35.52,139.72,118.155.230.132 +CA,BEACHBURG,ON,45.73,-76.85,72.246.43.237 +IN,HIMATNAGAR,GJ,23.60,72.95,117.239.189.111 +FR,CHEVREUSE,"",48.70,2.05,2.16.117.185 +IL,EINHAMIFRATZ,"",32.90,35.10,82.102.137.137 +RU,MAIKOP,"",44.61,40.11,80.239.237.93 +FR,BOULOGNESURMER,"",50.72,1.62,2.16.117.185 +US,GALVA,KS,38.3914,-97.5376,23.215.15.9 +US,REPUBLIC,MO,37.1404,-93.5188,23.77.234.35 +IR,CHAHARMAHAL,"",29.61,50.76,184.25.157.162 +DE,ANDERNACH,RP,50.43,7.40,23.14.94.228 +BR,PORTOVELHO,SP,-24.03,-46.72,187.59.4.147 +IT,VITO,"",38.13,15.70,96.17.180.155 +LT,VISAGINAS,"",55.60,26.42,92.122.189.85 +AT,KEMATEN,"",48.03,14.75,195.145.147.101 +PL,WARKA,"",51.78,21.20,2.22.52.105 +CI,BOUAKE,"",7.68,-5.03,23.0.162.40 +IR,MAHAN,"",34.18,48.21,184.25.157.162 +DK,HAARLEV,"",55.35,12.25,23.65.29.93 +CZ,BZENEC,"",48.98,17.27,195.27.155.188 +FR,CHATEAUDUN,"",48.08,1.33,2.16.117.200 +RO,CARACAL,"",45.02,24.88,88.221.93.150 +US,BARAGA,MI,46.8110,-88.5098,107.14.32.228 +CA,SALMONARM,BC,50.70,-119.28,184.27.179.159 +CA,PORTHARDY,BC,50.72,-127.50,184.27.179.159 +DE,FLORENBERG,HE,50.52,9.72,194.25.95.214 +TH,SAMUTPRAKAN,"",13.60,100.60,203.153.50.80 +IT,CESENA,"",44.14,12.25,2.20.142.166 +US,CARNEY,MI,45.5790,-87.5356,23.79.240.48 +CN,HEIHE,HL,50.27,127.47,184.84.239.175 +US,WADENA,MN,46.4558,-95.094,65.113.249.11 +FR,PONTEVEQUE,"",45.53,4.92,2.16.117.212 +PL,RADOSLAW,"",51.77,16.48,2.22.52.101 diff --git a/tests/large/sample/cp.csv b/tests/large/sample/cp.csv new file mode 100644 index 00000000..57d0074c --- /dev/null +++ b/tests/large/sample/cp.csv @@ -0,0 +1,3 @@ +113982 +277253 +323114 diff --git a/tests/large/sample/id.csv b/tests/large/sample/id.csv new file mode 100644 index 00000000..23b3c04c --- /dev/null +++ b/tests/large/sample/id.csv @@ -0,0 +1,100 @@ +ea7211754ec15b845ca906 +eab2c41754ec15b8124f9916-a +852612254ec15b81bbad91c +1007f54ec15b81341de68 +eae2ce1754ec15b810aac129 +ea12241754ec15b810397ca +2a3de1754ec15b8f18617f +ea82311754ec15b82e9bee9 +ea7291754ec15b876f64d47-a +1007f54ec15b838d595c2 +5dc1c11754ec15b87524 +eae2401754ec15b81e64092c +3cbe411754ec15b81a9f8da +abc3361754ec15b81a873d5 +ea7211754ec15b8231359ea-a +2c65421754ec15b8261e20a +f62d18b854ec15b899dd00a +ea6276054ec15b870c0e59-a +ea92341754ec15b87b147af +1682446854ec15b8c2ef917 +ea424f1754ec15b82fd3c688 +ea7211754ec15b823135fc9-a +ea92c11754ec15b8c577e60-a +ea82311754ec15b84122466f-a +eac2281754ec15b85354799 +ea7211754ec15b845ca8ff +ea62491754ec15b866af125-a +5dc1c11754ec15b8760c-a +ea424f1754ec15b83f96806-a +798e6ac54ec15b8205f877d +8e53e2ac54ec15b83a2d44c8 +8e53e2ac54ec15b81779f6c8 +ea62d11754ec15b84047f3b6 +545714254ec15b8261ef911-a +eae2ce1754ec15b810aac119 +1007f54ec15b8368562a +eac23b1754ec15b81a2f05 +eae2ce1754ec15b81f00403a +4032d1754ec15b84ef8f070 +1ff7201754ec15b81ca5de59 +eaf2251754ec15b847c3981 +eae2ce1754ec15b81f004033 +eab22b1754ec15b837f350c +abc3361754ec15b81a875bd +ea2361754ec15b84b66c3d6 +3863de1754ec15b840a41b6f-a +1007f54ec15b81ca5e0f4 +ea92311754ec15b81ba91fa4-a +1007f54ec15b8101f30ec +d47454b854ec15b83eeffc7 +a725d41754ec15b81c7c5873 +1007f54ec15b83757152a +1007f54ec15b837f5277 +ea12cc1754ec15b835e609e-a +ea2d31754ec15b88b1a11f +eab2d31754ec15b815a3d8a7-a +ea32251754ec15b838d595c2 +ea42d21754ec15b822711d5f +eac23b1754ec15b8f1cb626 +1007f54ec15b822710753 +3317a1754ec15b81b803928-a +c7872e1754ec15b82a4218a9-a +3317a1754ec15b81b80398d-a +eac23b1754ec15b8652720 +a39df1754ec15b81571b1c3-a +c7872e1754ec15b81fa5244e +ea7211754ec15b82313610e +ea2d31754ec15b8133f2c3c +13b5e2ac54ec15b8135fe4-a +abc3361754ec15b81a874cc +ea82361754ec15b8227494 +82db481754ec15b82c1f1327-a +d6b471754ec15b8210be9a3-a +ea723b1754ec15b85c05e90f-a +ea92341754ec15b87b147a3 +9ec34b1754ec15b8b132d9b-a +b4e14a1754ec15b81aea0e6c-a +1682446854ec15b8c2ef845-a +eaf2dfad54ec15b87630821 +ea7291754ec15b81ddfa729 +ea92c11754ec15b8c565b38 +1ff7201754ec15b81ca5d134 +ea12d61754ec15b8185ea12c +ea12d61754ec15b8185efa94 +8e53e2ac54ec15b81779f6b3 +82db481754ec15b82c1f0940-a +ea6261754ec15b8277ca2c6 +ead22e1754ec15b8618713-a +ea2411754ec15b869fc10a +8eaa436854ec15b812d62f36 +ea6261754ec15b81840a2f4 +3863de1754ec15b840a39abc +798e6ac54ec15b832b8f4e +7443211754ec15b83757152a +ea7211754ec15b845ca8f0 +218446854ec15b82b6381f9-a +9ec34b1754ec15b81591ba99 +c5e23a1754ec15b820275329 +ea92351754ec15b821848589 +eab2d31754ec15b815a3f23b diff --git a/tests/large/sample/ip.csv b/tests/large/sample/ip.csv new file mode 100644 index 00000000..cfe90552 --- /dev/null +++ b/tests/large/sample/ip.csv @@ -0,0 +1,100 @@ +23.1.114.234 +23.196.178.234 +2.18.38.133 +23.206.226.234 +23.36.18.234 +23.222.163.2 +23.49.130.234 +23.9.114.234 +23.193.193.93 +23.64.226.234 +23.65.190.60 +23.54.195.171 +23.66.101.44 +184.24.45.246 +96.7.98.234 +23.52.146.234 +104.68.130.22 +23.79.66.234 +23.193.146.234 +23.40.194.234 +23.73.98.234 +172.230.152.7 +172.226.83.142 +23.209.98.234 +2.20.87.84 +23.59.194.234 +23.13.50.64 +23.32.247.31 +23.37.242.234 +23.43.178.234 +23.54.2.234 +23.222.99.56 +23.49.146.234 +184.84.116.212 +23.212.37.167 +23.204.18.234 +23.211.2.234 +23.211.178.234 +23.37.50.234 +23.210.66.234 +23.10.23.51 +23.46.135.199 +23.223.57.10 +172.226.181.19 +23.54.130.234 +23.72.219.130 +23.7.180.214 +23.59.114.234 +23.75.195.158 +23.74.225.180 +173.223.242.234 +23.214.18.234 +23.6.98.234 +23.46.210.234 +23.65.2.234 +104.67.170.142 +23.33.67.116 +104.68.8.33 +23.58.226.197 +23.53.146.234 +23.77.18.234 +23.63.195.40 +2.20.98.234 +96.16.220.139 +23.50.146.234 +184.51.208.185 +23.201.210.234 +23.41.0.20 +23.194.50.234 +23.214.154.131 +95.100.126.200 +172.229.194.234 +23.50.82.234 +23.4.132.102 +23.79.99.50 +23.218.215.93 +23.203.2.234 +23.57.210.234 +23.195.122.147 +23.64.114.13 +23.37.151.160 +23.53.210.234 +172.231.252.196 +104.73.32.231 +23.43.66.234 +23.197.11.186 +23.73.162.234 +23.51.51.183 +23.220.18.234 +104.66.212.185 +23.73.2.234 +23.63.84.195 +23.212.200.244 +2.16.47.42 +172.233.88.222 +23.49.226.234 +23.74.82.234 +23.76.178.234 +23.212.226.234 +23.36.34.234 diff --git a/tests/large/sample/replay b/tests/large/sample/replay new file mode 100755 index 00000000..b906dc98 --- /dev/null +++ b/tests/large/sample/replay @@ -0,0 +1,12 @@ +2014-01-04 20:00:00 WINDBAG Event 1 of 12 randint @@integer +2014-01-04 20:00:01 WINDBAG Event 2 of 12 randint @@integer +2014-01-04 20:00:02 WINDBAG Event 3 of 12 randint @@integer +2014-01-04 20:00:03 WINDBAG Event 4 of 12 randint @@integer +2014-01-04 20:00:03 WINDBAG Event 5 of 12 randint @@integer +2014-01-04 20:00:04 WINDBAG Event 6 of 12 randint @@integer +2014-01-04 20:00:05 WINDBAG Event 7 of 12 randint @@integer +2014-01-04 20:00:06 WINDBAG Event 8 of 12 randint @@integer +2014-01-04 20:00:08 WINDBAG Event 9 of 12 randint @@integer +2014-01-04 20:00:20 WINDBAG Event 10 of 12 randint @@integer +2014-01-04 20:00:21 WINDBAG Event 11 of 12 randint @@integer +2014-01-04 20:00:21 WINDBAG Event 12 of 12 randint @@integer diff --git a/tests/large/sample/sample b/tests/large/sample/sample new file mode 100755 index 00000000..b906dc98 --- /dev/null +++ b/tests/large/sample/sample @@ -0,0 +1,12 @@ +2014-01-04 20:00:00 WINDBAG Event 1 of 12 randint @@integer +2014-01-04 20:00:01 WINDBAG Event 2 of 12 randint @@integer +2014-01-04 20:00:02 WINDBAG Event 3 of 12 randint @@integer +2014-01-04 20:00:03 WINDBAG Event 4 of 12 randint @@integer +2014-01-04 20:00:03 WINDBAG Event 5 of 12 randint @@integer +2014-01-04 20:00:04 WINDBAG Event 6 of 12 randint @@integer +2014-01-04 20:00:05 WINDBAG Event 7 of 12 randint @@integer +2014-01-04 20:00:06 WINDBAG Event 8 of 12 randint @@integer +2014-01-04 20:00:08 WINDBAG Event 9 of 12 randint @@integer +2014-01-04 20:00:20 WINDBAG Event 10 of 12 randint @@integer +2014-01-04 20:00:21 WINDBAG Event 11 of 12 randint @@integer +2014-01-04 20:00:21 WINDBAG Event 12 of 12 randint @@integer diff --git a/tests/large/sample/timeorder.csv b/tests/large/sample/timeorder.csv new file mode 100644 index 00000000..72e2fc31 --- /dev/null +++ b/tests/large/sample/timeorder.csv @@ -0,0 +1,11 @@ +_time,_raw,index,host,source,sourcetype +2015-08-18T16:28:54.695-0700,"127.0.0.1 - admin [18/Aug/2015:16:28:54.695 -0700] ""GET /en-US/api/shelper?snippet=true&snippetEmbedJS=false&namespace=search&search=search+index%3D_internal+%7C+fields+_time%2C+_raw%2C+index%2C+host%2C+source%2C+sourcetype+&useTypeahead=true&useAssistant=true&showCommandHelp=true&showCommandHistory=true&showFieldInfo=false&_=1439940537886 HTTP/1.1"" 200 994 ""https://host5.foobar.com:8000/en-US/app/search/search?q=search%20index%3D_internal%20%7C%20fields%20_time%2C%20_raw%2C%20index%2C%20host%2C%20source%2C%20sourcetype&sid=1439940529.1846224&earliest=&latest="" ""Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36"" - 55d3bfb6b17f7ff8270d50 33ms",_internal,host5.foobar.com,/usr/local/bamboo/itsi-demo/local/splunk/var/log/splunk/web_access.log,splunk_web_access +2015-08-18T16:28:54.569-0700,"2015-08-18 16:28:54,569 INFO streams_utils:24 - utils::readAsJson:: /usr/local/bamboo/itsi-demo/local/splunk/etc/apps/splunk_app_stream/local/apps",_internal,host5.foobar.com,/usr/local/bamboo/itsi-demo/local/splunk/var/log/splunk/splunk_app_stream.log,splunk_app_stream.log +2015-08-18T16:28:54.568-0700,"2015-08-18 16:28:54,568 INFO streams_utils:74 - create dir /usr/local/bamboo/itsi-demo/local/splunk/etc/apps/splunk_app_stream/local/",_internal,host5.foobar.com,/usr/local/bamboo/itsi-demo/local/splunk/var/log/splunk/splunk_app_stream.log,splunk_app_stream.log +2015-08-18T16:28:54.564-0700,"127.0.0.1 - - [18/Aug/2015:16:28:54.564 -0700] ""GET /en-us/custom/splunk_app_stream/ping/ HTTP/1.1"" 200 311 """" """" - 55d3bfb6907f7ff805f710 5ms",_internal,host5.foobar.com,/usr/local/bamboo/itsi-demo/local/splunk/var/log/splunk/web_access.log,splunk_web_access +2015-08-18T16:28:52.798-0700,"10.160.255.115 - admin [18/Aug/2015:16:28:52.798 -0700] ""GET /en-US/splunkd/__raw/servicesNS/nobody/search/search/jobs/1439940529.1846224/summary?output_mode=json&min_freq=0&_=1439940537880 HTTP/1.1"" 200 503 ""https://host5.foobar.com:8000/en-US/app/search/search?q=search%20index%3D_internal%20%7C%20fields%20_time%2C%20_raw%2C%20index%2C%20host%2C%20source%2C%20sourcetype&sid=1439940529.1846224&earliest=&latest="" ""Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36"" - 9f802569d5c3d77d468e897d34f8969f 6ms",_internal,host5.foobar.com,/usr/local/bamboo/itsi-demo/local/splunk/var/log/splunk/splunkd_ui_access.log,splunkd_ui_access +2015-08-18T16:28:52.798-0700,"10.160.255.115 - admin [18/Aug/2015:16:28:52.798 -0700] ""GET /en-US/splunkd/__raw/services/search/jobs/1439940529.1846224/timeline?offset=0&count=1000&_=1439940537881 HTTP/1.1"" 200 349 ""https://host5.foobar.com:8000/en-US/app/search/search?q=search%20index%3D_internal%20%7C%20fields%20_time%2C%20_raw%2C%20index%2C%20host%2C%20source%2C%20sourcetype&sid=1439940529.1846224&earliest=&latest="" ""Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36"" - 9f802569d5c3d77d468e897d34f8969f 4ms",_internal,host5.foobar.com,/usr/local/bamboo/itsi-demo/local/splunk/var/log/splunk/splunkd_ui_access.log,splunkd_ui_access +2015-08-18T16:28:52.754-0700,"10.160.255.115 - admin [18/Aug/2015:16:28:52.754 -0700] ""GET /en-US/splunkd/__raw/servicesNS/nobody/search/search/jobs/1439940529.1846224?output_mode=json&_=1439940537879 HTTP/1.1"" 200 1543 ""https://host5.foobar.com:8000/en-US/app/search/search?q=search%20index%3D_internal%20%7C%20fields%20_time%2C%20_raw%2C%20index%2C%20host%2C%20source%2C%20sourcetype&sid=1439940529.1846224&earliest=&latest="" ""Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36"" - 9f802569d5c3d77d468e897d34f8969f 4ms",_internal,host5.foobar.com,/usr/local/bamboo/itsi-demo/local/splunk/var/log/splunk/splunkd_ui_access.log,splunkd_ui_access +2015-08-18T16:28:52.270-0700,"2015-08-18 16:28:52,270 ERROR pid=16324 tid=MainThread file=__init__.py:execute:957 | Execution failed: [HTTP 401] Client is not authenticated +2015-08-18T16:28:52.268-0700,"127.0.0.1 - - [18/Aug/2015:16:28:52.268 -0700] ""GET /services/shcluster/config/config HTTP/1.0"" 401 148 - - - 0ms",_internal,host5.foobar.com,/usr/local/bamboo/itsi-demo/local/splunk/var/log/splunk/splunkd_access.log,splunkd_access +2015-08-18T16:28:52.247-0700,"2015-08-18 16:28:52,247 INFO pid=16324 tid=MainThread file=__init__.py:execute:906 | Execute called",_internal,host5.foobar.com,/usr/local/bamboo/itsi-demo/local/splunk/var/log/splunk/python_modular_input.log,python_modular_input diff --git a/tests/large/sample/tokenreplacement.sample b/tests/large/sample/tokenreplacement.sample new file mode 100644 index 00000000..59dbc485 --- /dev/null +++ b/tests/large/sample/tokenreplacement.sample @@ -0,0 +1,10 @@ +{"type":"cloud_monitor","format":"default","version":"1.0","id":"ea7211754ec15b845ca906","start":"1424758200.997","cp":"113982","message":{"reqQuery":"cmd%3d_dummyaccessrequest-submit%26dispatch%3d5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e","reqLen":68,"reqCT":"application%2fjson%3b%20charset%3dUTF-8","proto":"http","protoVer":"1.1","status":"301","cliIP":"999.254.16.5","reqPort":"80","reqHost":"www.dummycompanytest.com","reqMethod":"GET","reqPath":"%2f","respLen":"0","bytes":"0","UA":"PowerShell%20Script","fwdHost":"origin-www.dummycompanytest.com.akadns.net"},"netPerf":{"downloadTime":"2","lastMileRTT":"22","cacheStatus":"0","firstByte":"0","lastByte":"1","asnum":"25667","edgeIP":"23.74.2.12"},"geo":{"country":"US","region":"GA","city":"ATLANTA","lat":"33.7486","long":"-84.3884"},"network":{"edgeIP":"23.74.2.12","asnum":"25667","network":"","networkType":""},"akadebug":{"Ak_IP":"23.1.114.234","akam-server-type":"Production","current-time":"1424758200","forward-origin-ip":"10.10.10.10","end-user-ip":"999.254.16.5","akamai-request-id":"45ca906","cpcode":"113982","origin-timeout":"no"},"ppcustomdata":{"hostheader":"","cmd":"","receiver_id":"","ADS":""},"reqHdr":{"accEnc":"gzip","referer":"https://www.splunk.com","cookie":"firebrowser","conn":"Keep-Alive"}} +{"type":"cloud_monitor","format":"default","version":"1.0","id":"ea7211754ec15b845ca906","start":"1424758200.997","cp":"113982","message":{"reqQuery":"cmd%3d_dummyaccessrequest-submit%26dispatch%3d5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e","reqLen":68,"reqCT":"application%2fjson%3b%20charset%3dUTF-8","proto":"http","protoVer":"1.1","status":"301","cliIP":"999.254.16.5","reqPort":"80","reqHost":"www.dummycompanytest.com","reqMethod":"GET","reqPath":"%2f","respLen":"0","bytes":"0","UA":"PowerShell%20Script","fwdHost":"origin-www.dummycompanytest.com.akadns.net"},"netPerf":{"downloadTime":"2","lastMileRTT":"22","cacheStatus":"0","firstByte":"0","lastByte":"1","asnum":"25667","edgeIP":"23.74.2.12"},"geo":{"country":"US","region":"GA","city":"ATLANTA","lat":"33.7486","long":"-84.3884"},"network":{"edgeIP":"23.74.2.12","asnum":"25667","network":"","networkType":""},"akadebug":{"Ak_IP":"23.1.114.234","akam-server-type":"Production","current-time":"1424758200","forward-origin-ip":"10.10.10.10","end-user-ip":"999.254.16.5","akamai-request-id":"45ca906","cpcode":"113982","origin-timeout":"no"},"ppcustomdata":{"hostheader":"","cmd":"","receiver_id":"","ADS":""},"reqHdr":{"accEnc":"gzip","referer":"https://www.splunk.com","cookie":"firebrowser","conn":"Keep-Alive"}} +{"type":"cloud_monitor","format":"default","version":"1.0","id":"ea7211754ec15b845ca906","start":"1424758200.997","cp":"113982","message":{"reqQuery":"cmd%3d_dummyaccessrequest-submit%26dispatch%3d5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e","reqLen":68,"reqCT":"application%2fjson%3b%20charset%3dUTF-8","proto":"http","protoVer":"1.1","status":"301","cliIP":"999.254.16.5","reqPort":"80","reqHost":"www.dummycompanytest.com","reqMethod":"GET","reqPath":"%2f","respLen":"0","bytes":"0","UA":"PowerShell%20Script","fwdHost":"origin-www.dummycompanytest.com.akadns.net"},"netPerf":{"downloadTime":"2","lastMileRTT":"22","cacheStatus":"0","firstByte":"0","lastByte":"1","asnum":"25667","edgeIP":"23.74.2.12"},"geo":{"country":"US","region":"GA","city":"ATLANTA","lat":"33.7486","long":"-84.3884"},"network":{"edgeIP":"23.74.2.12","asnum":"25667","network":"","networkType":""},"akadebug":{"Ak_IP":"23.1.114.234","akam-server-type":"Production","current-time":"1424758200","forward-origin-ip":"10.10.10.10","end-user-ip":"999.254.16.5","akamai-request-id":"45ca906","cpcode":"113982","origin-timeout":"no"},"ppcustomdata":{"hostheader":"","cmd":"","receiver_id":"","ADS":""},"reqHdr":{"accEnc":"gzip","referer":"https://www.splunk.com","cookie":"firebrowser","conn":"Keep-Alive"}} +{"type":"cloud_monitor","format":"default","version":"1.0","id":"ea7211754ec15b845ca906","start":"1424758200.997","cp":"113982","message":{"reqQuery":"cmd%3d_dummyaccessrequest-submit%26dispatch%3d5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e","reqLen":68,"reqCT":"application%2fjson%3b%20charset%3dUTF-8","proto":"http","protoVer":"1.1","status":"301","cliIP":"999.254.16.5","reqPort":"80","reqHost":"www.dummycompanytest.com","reqMethod":"GET","reqPath":"%2f","respLen":"0","bytes":"0","UA":"PowerShell%20Script","fwdHost":"origin-www.dummycompanytest.com.akadns.net"},"netPerf":{"downloadTime":"2","lastMileRTT":"22","cacheStatus":"0","firstByte":"0","lastByte":"1","asnum":"25667","edgeIP":"23.74.2.12"},"geo":{"country":"US","region":"GA","city":"ATLANTA","lat":"33.7486","long":"-84.3884"},"network":{"edgeIP":"23.74.2.12","asnum":"25667","network":"","networkType":""},"akadebug":{"Ak_IP":"23.1.114.234","akam-server-type":"Production","current-time":"1424758200","forward-origin-ip":"10.10.10.10","end-user-ip":"999.254.16.5","akamai-request-id":"45ca906","cpcode":"113982","origin-timeout":"no"},"ppcustomdata":{"hostheader":"","cmd":"","receiver_id":"","ADS":""},"reqHdr":{"accEnc":"gzip","referer":"https://www.splunk.com","cookie":"firebrowser","conn":"Keep-Alive"}} +{"type":"cloud_monitor","format":"default","version":"1.0","id":"ea7211754ec15b845ca906","start":"1424758200.997","cp":"113982","message":{"reqQuery":"cmd%3d_dummyaccessrequest-submit%26dispatch%3d5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e","reqLen":68,"reqCT":"application%2fjson%3b%20charset%3dUTF-8","proto":"http","protoVer":"1.1","status":"301","cliIP":"999.254.16.5","reqPort":"80","reqHost":"www.dummycompanytest.com","reqMethod":"GET","reqPath":"%2f","respLen":"0","bytes":"0","UA":"PowerShell%20Script","fwdHost":"origin-www.dummycompanytest.com.akadns.net"},"netPerf":{"downloadTime":"2","lastMileRTT":"22","cacheStatus":"0","firstByte":"0","lastByte":"1","asnum":"25667","edgeIP":"23.74.2.12"},"geo":{"country":"US","region":"GA","city":"ATLANTA","lat":"33.7486","long":"-84.3884"},"network":{"edgeIP":"23.74.2.12","asnum":"25667","network":"","networkType":""},"akadebug":{"Ak_IP":"23.1.114.234","akam-server-type":"Production","current-time":"1424758200","forward-origin-ip":"10.10.10.10","end-user-ip":"999.254.16.5","akamai-request-id":"45ca906","cpcode":"113982","origin-timeout":"no"},"ppcustomdata":{"hostheader":"","cmd":"","receiver_id":"","ADS":""},"reqHdr":{"accEnc":"gzip","referer":"https://www.splunk.com","cookie":"firebrowser","conn":"Keep-Alive"}} +{"type":"cloud_monitor","format":"default","version":"1.0","id":"ea7211754ec15b845ca906","start":"1424758200.997","cp":"113982","message":{"reqQuery":"cmd%3d_dummyaccessrequest-submit%26dispatch%3d5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e","reqLen":68,"reqCT":"application%2fjson%3b%20charset%3dUTF-8","proto":"http","protoVer":"1.1","status":"301","cliIP":"999.254.16.5","reqPort":"80","reqHost":"www.dummycompanytest.com","reqMethod":"GET","reqPath":"%2f","respLen":"0","bytes":"0","UA":"PowerShell%20Script","fwdHost":"origin-www.dummycompanytest.com.akadns.net"},"netPerf":{"downloadTime":"2","lastMileRTT":"22","cacheStatus":"0","firstByte":"0","lastByte":"1","asnum":"25667","edgeIP":"23.74.2.12"},"geo":{"country":"US","region":"GA","city":"ATLANTA","lat":"33.7486","long":"-84.3884"},"network":{"edgeIP":"23.74.2.12","asnum":"25667","network":"","networkType":""},"akadebug":{"Ak_IP":"23.1.114.234","akam-server-type":"Production","current-time":"1424758200","forward-origin-ip":"10.10.10.10","end-user-ip":"999.254.16.5","akamai-request-id":"45ca906","cpcode":"113982","origin-timeout":"no"},"ppcustomdata":{"hostheader":"","cmd":"","receiver_id":"","ADS":""},"reqHdr":{"accEnc":"gzip","referer":"https://www.splunk.com","cookie":"firebrowser","conn":"Keep-Alive"}} +{"type":"cloud_monitor","format":"default","version":"1.0","id":"ea7211754ec15b845ca906","start":"1424758200.997","cp":"113982","message":{"reqQuery":"cmd%3d_dummyaccessrequest-submit%26dispatch%3d5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e","reqLen":68,"reqCT":"application%2fjson%3b%20charset%3dUTF-8","proto":"http","protoVer":"1.1","status":"301","cliIP":"999.254.16.5","reqPort":"80","reqHost":"www.dummycompanytest.com","reqMethod":"GET","reqPath":"%2f","respLen":"0","bytes":"0","UA":"PowerShell%20Script","fwdHost":"origin-www.dummycompanytest.com.akadns.net"},"netPerf":{"downloadTime":"2","lastMileRTT":"22","cacheStatus":"0","firstByte":"0","lastByte":"1","asnum":"25667","edgeIP":"23.74.2.12"},"geo":{"country":"US","region":"GA","city":"ATLANTA","lat":"33.7486","long":"-84.3884"},"network":{"edgeIP":"23.74.2.12","asnum":"25667","network":"","networkType":""},"akadebug":{"Ak_IP":"23.1.114.234","akam-server-type":"Production","current-time":"1424758200","forward-origin-ip":"10.10.10.10","end-user-ip":"999.254.16.5","akamai-request-id":"45ca906","cpcode":"113982","origin-timeout":"no"},"ppcustomdata":{"hostheader":"","cmd":"","receiver_id":"","ADS":""},"reqHdr":{"accEnc":"gzip","referer":"https://www.splunk.com","cookie":"firebrowser","conn":"Keep-Alive"}} +{"type":"cloud_monitor","format":"default","version":"1.0","id":"ea7211754ec15b845ca906","start":"1424758200.997","cp":"113982","message":{"reqQuery":"cmd%3d_dummyaccessrequest-submit%26dispatch%3d5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e","reqLen":68,"reqCT":"application%2fjson%3b%20charset%3dUTF-8","proto":"http","protoVer":"1.1","status":"301","cliIP":"999.254.16.5","reqPort":"80","reqHost":"www.dummycompanytest.com","reqMethod":"GET","reqPath":"%2f","respLen":"0","bytes":"0","UA":"PowerShell%20Script","fwdHost":"origin-www.dummycompanytest.com.akadns.net"},"netPerf":{"downloadTime":"2","lastMileRTT":"22","cacheStatus":"0","firstByte":"0","lastByte":"1","asnum":"25667","edgeIP":"23.74.2.12"},"geo":{"country":"US","region":"GA","city":"ATLANTA","lat":"33.7486","long":"-84.3884"},"network":{"edgeIP":"23.74.2.12","asnum":"25667","network":"","networkType":""},"akadebug":{"Ak_IP":"23.1.114.234","akam-server-type":"Production","current-time":"1424758200","forward-origin-ip":"10.10.10.10","end-user-ip":"999.254.16.5","akamai-request-id":"45ca906","cpcode":"113982","origin-timeout":"no"},"ppcustomdata":{"hostheader":"","cmd":"","receiver_id":"","ADS":""},"reqHdr":{"accEnc":"gzip","referer":"https://www.splunk.com","cookie":"firebrowser","conn":"Keep-Alive"}} +{"type":"cloud_monitor","format":"default","version":"1.0","id":"ea7211754ec15b845ca906","start":"1424758200.997","cp":"113982","message":{"reqQuery":"cmd%3d_dummyaccessrequest-submit%26dispatch%3d5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e","reqLen":68,"reqCT":"application%2fjson%3b%20charset%3dUTF-8","proto":"http","protoVer":"1.1","status":"301","cliIP":"999.254.16.5","reqPort":"80","reqHost":"www.dummycompanytest.com","reqMethod":"GET","reqPath":"%2f","respLen":"0","bytes":"0","UA":"PowerShell%20Script","fwdHost":"origin-www.dummycompanytest.com.akadns.net"},"netPerf":{"downloadTime":"2","lastMileRTT":"22","cacheStatus":"0","firstByte":"0","lastByte":"1","asnum":"25667","edgeIP":"23.74.2.12"},"geo":{"country":"US","region":"GA","city":"ATLANTA","lat":"33.7486","long":"-84.3884"},"network":{"edgeIP":"23.74.2.12","asnum":"25667","network":"","networkType":""},"akadebug":{"Ak_IP":"23.1.114.234","akam-server-type":"Production","current-time":"1424758200","forward-origin-ip":"10.10.10.10","end-user-ip":"999.254.16.5","akamai-request-id":"45ca906","cpcode":"113982","origin-timeout":"no"},"ppcustomdata":{"hostheader":"","cmd":"","receiver_id":"","ADS":""},"reqHdr":{"accEnc":"gzip","referer":"https://www.splunk.com","cookie":"firebrowser","conn":"Keep-Alive"}} +{"type":"cloud_monitor","format":"default","version":"1.0","id":"ea7211754ec15b845ca906","start":"1424758200.997","cp":"113982","message":{"reqQuery":"cmd%3d_dummyaccessrequest-submit%26dispatch%3d5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e","reqLen":68,"reqCT":"application%2fjson%3b%20charset%3dUTF-8","proto":"http","protoVer":"1.1","status":"301","cliIP":"999.254.16.5","reqPort":"80","reqHost":"www.dummycompanytest.com","reqMethod":"GET","reqPath":"%2f","respLen":"0","bytes":"0","UA":"PowerShell%20Script","fwdHost":"origin-www.dummycompanytest.com.akadns.net"},"netPerf":{"downloadTime":"2","lastMileRTT":"22","cacheStatus":"0","firstByte":"0","lastByte":"1","asnum":"25667","edgeIP":"23.74.2.12"},"geo":{"country":"US","region":"GA","city":"ATLANTA","lat":"33.7486","long":"-84.3884"},"network":{"edgeIP":"23.74.2.12","asnum":"25667","network":"","networkType":""},"akadebug":{"Ak_IP":"23.1.114.234","akam-server-type":"Production","current-time":"1424758200","forward-origin-ip":"10.10.10.10","end-user-ip":"999.254.16.5","akamai-request-id":"45ca906","cpcode":"113982","origin-timeout":"no"},"ppcustomdata":{"hostheader":"","cmd":"","receiver_id":"","ADS":""},"reqHdr":{"accEnc":"gzip","referer":"https://www.splunk.com","cookie":"firebrowser","conn":"Keep-Alive"}} diff --git a/tests/large/test_eventgen_orchestration.py b/tests/large/test_eventgen_orchestration.py index d5bc7cbe..19d35da3 100644 --- a/tests/large/test_eventgen_orchestration.py +++ b/tests/large/test_eventgen_orchestration.py @@ -1,16 +1,18 @@ #!/usr/bin/env python # encoding: utf-8 +import json import os import time -import json +from random import choice +from string import ascii_lowercase + import pytest import requests from docker import APIClient -from random import choice -from string import ascii_lowercase # Code to suppress insecure https warnings from requests.packages.urllib3.exceptions import InsecureRequestWarning + requests.packages.urllib3.disable_warnings(InsecureRequestWarning) FILE_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -18,12 +20,14 @@ IMAGE_NAME = "eventgen:test" NETWORK_NAME = "eg_network_test" + def generate_random_string(): return ''.join(choice(ascii_lowercase) for b in range(20)) + def wait_for_response(url, timeout=60): start, end = time.time(), time.time() - while end-start < timeout: + while end - start < timeout: try: r = requests.get(url) r.raise_for_status() @@ -35,249 +39,260 @@ def wait_for_response(url, timeout=60): @pytest.mark.large class TestEventgenOrchestration(object): - ''' - This test class is used to test the Docker image published as part of this repo. - Specifically, this is testing: - * Eventgen "controller" API and responses - * Eventgen "server" API and responses - * Eventgen controller/server orchestration - ''' - - @classmethod - def setup_class(cls): - # Build the image from scratch - cls.client = APIClient(base_url="unix://var/run/docker.sock") - response = cls.client.build(path=REPO_DIR, dockerfile=os.path.join("dockerfiles", "Dockerfile"), tag=IMAGE_NAME, rm=True, nocache=True, pull=True, stream=False) - for line in response: - print line, - # Create a network for both the controller + server to run in - cls.client.create_network(NETWORK_NAME, driver="bridge", attachable=True) - networking_config = cls.client.create_networking_config({NETWORK_NAME: cls.client.create_endpoint_config()}) - # Start the controller - print 'creating controller' - host_config = cls.client.create_host_config(auto_remove=True, publish_all_ports=True) - container = cls.client.create_container(image=IMAGE_NAME, - command="controller", - host_config=host_config, - networking_config=networking_config) - cls.client.start(container["Id"]) - TestEventgenOrchestration.controller_id = container["Id"] - print container["Id"] - cls.controller_container = cls.client.inspect_container(container["Id"]) - cls.controller_eventgen_webport = cls.controller_container["NetworkSettings"]["Ports"]["9500/tcp"][0]["HostPort"] - cls.controller_rabbitmq_webport = cls.controller_container["NetworkSettings"]["Ports"]["15672/tcp"][0]["HostPort"] - # Start the server - print 'creating server' - container = cls.client.create_container(image=IMAGE_NAME, - command="server", - environment=["EVENTGEN_AMQP_HOST={}".format(cls.controller_container["Id"][:12])], - host_config=host_config, - networking_config=networking_config) - cls.client.start(container["Id"]) - TestEventgenOrchestration.server_id = container["Id"] - print container["Id"] - cls.server_container = cls.client.inspect_container(container["Id"]) - cls.server_eventgen_webport = cls.server_container["NetworkSettings"]["Ports"]["9500/tcp"][0]["HostPort"] - cls.server_rabbitmq_webport = cls.server_container["NetworkSettings"]["Ports"]["15672/tcp"][0]["HostPort"] - # Wait for the controller to be available - print "Waiting for Eventgen Controller to become available." - wait_for_response("http://127.0.0.1:{}".format(cls.controller_eventgen_webport)) - print "Eventgen Controller has become available." - # Wait for the server to be available - print "Waiting for Eventgen Server to become available." - wait_for_response("http://127.0.0.1:{}".format(cls.server_eventgen_webport)) - print "Eventgen Server has become available." - time.sleep(60) - - @classmethod - def teardown_class(cls): - cls.client.remove_container(cls.server_container, v=True, force=True) - cls.client.remove_container(cls.controller_container, v=True, force=True) - cls.client.remove_image(IMAGE_NAME, force=True, noprune=False) - cls.client.remove_network(NETWORK_NAME) - - ### Controller tests ### - - def test_controller_rabbitmq(self): - r = requests.get("http://127.0.0.1:{}".format(self.controller_rabbitmq_webport)) - assert r.status_code == 200 - assert "RabbitMQ" in r.content - - def test_controller_root(self): - r = requests.get("http://127.0.0.1:{}".format(self.controller_eventgen_webport)) - assert r.status_code == 200 - assert "Eventgen Controller" in r.content - assert "Host: " in r.content - assert "You are running Eventgen Controller" in r.content - - def test_controller_index(self): - r = requests.get("http://127.0.0.1:{}/index".format(self.controller_eventgen_webport)) - assert r.status_code == 200 - assert "Eventgen Controller" in r.content - assert "Host: " in r.content - assert "You are running Eventgen Controller" in r.content - - def test_controller_status(self): - max_retry = 5 - current_retry = 1 - output = {} - while not output and current_retry <= max_retry: - response = requests.get("http://127.0.0.1:{}/status".format(self.controller_eventgen_webport), timeout=10) - if response.status_code == 200: - output = json.loads(response.content) - current_retry += 1 - time.sleep(10) - assert output - - def test_controller_start(self): - r = requests.post("http://127.0.0.1:{}/start".format(self.controller_eventgen_webport)) - assert r.status_code == 200 - assert "Start event dispatched to all" in r.content - - def test_controller_start_with_target(self): - r = requests.post("http://127.0.0.1:{}/start/{}".format(self.controller_eventgen_webport, TestEventgenOrchestration.server_id[:12])) - assert r.status_code == 200 - assert "Start event dispatched to {}".format(TestEventgenOrchestration.server_id[:12]) in r.content - - def test_controller_stop(self): - r = requests.post("http://127.0.0.1:{}/stop".format(self.controller_eventgen_webport)) - assert r.status_code == 200 - assert "Stop event dispatched to all" in r.content - - def test_controller_stop_with_target(self): - r = requests.post("http://127.0.0.1:{}/stop/{}".format(self.controller_eventgen_webport, TestEventgenOrchestration.server_id[:12])) - assert r.status_code == 200 - assert "Stop event dispatched to {}".format(TestEventgenOrchestration.server_id[:12]) in r.content - - def test_controller_restart(self): - r = requests.post("http://127.0.0.1:{}/stop".format(self.controller_eventgen_webport)) - assert r.status_code == 200 - assert "Stop event dispatched to all" in r.content - - def test_controller_restart_with_target(self): - r = requests.post("http://127.0.0.1:{}/stop/{}".format(self.controller_eventgen_webport, TestEventgenOrchestration.server_id[:12])) - assert r.status_code == 200 - assert "Stop event dispatched to {}".format(TestEventgenOrchestration.server_id[:12]) in r.content - - def test_controller_bundle_invalid_request(self): - r = requests.post("http://127.0.0.1:{}/bundle".format(self.controller_eventgen_webport)) - assert r.status_code == 400 - assert "Please pass in a valid object with bundle URL" in r.content - - def test_controller_bundle_with_url(self): - r = requests.post("http://127.0.0.1:{}/bundle".format(self.controller_eventgen_webport), json={"url": "http://server.com/bundle.tgz"}) - assert r.status_code == 200 - assert "Bundle event dispatched to all with url http://server.com/bundle.tgz" in r.content - - def test_controller_bundle_with_url_and_target(self): - r = requests.post("http://127.0.0.1:{}/bundle/{}".format(self.controller_eventgen_webport, TestEventgenOrchestration.server_id[:12]), json={"url": "http://server.com/bundle.tgz"}) - assert r.status_code == 200 - assert "Bundle event dispatched to {} with url http://server.com/bundle.tgz".format(TestEventgenOrchestration.server_id[:12]) in r.content - - @pytest.mark.skip(reason="Change in implementation") - def test_controller_get_volume(self): - max_retry = 5 - current_retry = 1 - output = {} - while not output and current_retry <= max_retry: - response = requests.get("http://127.0.0.1:{}/volume".format(self.controller_eventgen_webport), timeout=10) - if response.status_code == 200: - output = json.loads(response.content) - current_retry += 1 - time.sleep(10) - assert output[TestEventgenOrchestration.server_id[:12]] == 0.0 - - def test_controller_set_volume_invalid_request(self): - r = requests.post("http://127.0.0.1:{}/volume".format(self.controller_eventgen_webport)) - assert r.status_code == 400 - assert "Please pass in a valid object with volume" in r.content - - def test_controller_set_volume_with_volume(self): - r = requests.post("http://127.0.0.1:{}/volume".format(self.controller_eventgen_webport), json={"perDayVolume": 10}) - assert r.status_code == 200 - assert "set_volume event dispatched to all" in r.content - - def test_controller_set_volume_with_volume_and_target(self): - r = requests.post("http://127.0.0.1:{}/volume/{}".format(self.controller_eventgen_webport, TestEventgenOrchestration.server_id[:12]), json={"perDayVolume": 10}) - assert r.status_code == 200 - assert "set_volume event dispatched to {}".format(TestEventgenOrchestration.server_id[:12]) in r.content - - ### Server tests ### - - def test_server_root(self): - r = requests.get("http://127.0.0.1:{}".format(self.server_eventgen_webport)) - assert r.status_code == 200 - assert "Host: " in r.content - assert "Eventgen Status" in r.content - assert "Eventgen Config file path" in r.content - assert "Total volume:" in r.content - assert "Worker Queue Status" in r.content - assert "Sample Queue Status" in r.content - assert "Output Queue Status" in r.content - - def test_server_index(self): - r = requests.get("http://127.0.0.1:{}/index".format(self.server_eventgen_webport)) - assert r.status_code == 200 - assert "Host: " in r.content - assert "Eventgen Status" in r.content - assert "Eventgen Config file path" in r.content - assert "Total volume:" in r.content - assert "Worker Queue Status" in r.content - assert "Sample Queue Status" in r.content - assert "Output Queue Status" in r.content - - def test_server_status(self): - r = requests.get("http://127.0.0.1:{}/status".format(self.server_eventgen_webport)) - assert r.status_code == 200 - output = json.loads(r.content) - assert output - assert output['EVENTGEN_STATUS'] == 0 - - def test_server_get_and_set_conf(self): - r = requests.get("http://127.0.0.1:{}/conf".format(self.server_eventgen_webport)) - assert r.status_code == 200 - assert json.loads(r.content) == {} - config_json = {"windbag": {"outputMode": "stdout"}} - r = requests.post("http://127.0.0.1:{}/conf".format(self.server_eventgen_webport), json=config_json) - assert r.status_code == 200 - assert json.loads(r.content) == config_json - - def test_server_start(self): - r = requests.post("http://127.0.0.1:{}/start".format(self.server_eventgen_webport), timeout=5) - assert r.status_code == 200 - assert json.loads(r.content) == "Eventgen has successfully started." - - def test_server_restart(self): - r = requests.post("http://127.0.0.1:{}/restart".format(self.server_eventgen_webport)) - assert r.status_code == 200 - assert json.loads(r.content) == "Eventgen restarted." - - def test_server_stop(self): - r = requests.post("http://127.0.0.1:{}/stop".format(self.server_eventgen_webport)) - assert r.status_code == 200 - assert json.loads(r.content) == "Eventgen is stopped." - - def test_server_bundle(self): - r = requests.post("http://127.0.0.1:{}/bundle".format(self.server_eventgen_webport)) - assert r.status_code == 400 - assert "Please pass in a valid object with bundle URL" in r.content - - def test_server_get_and_set_volume(self): - # Must initialize a stanza with the perDayVolume setting before hitting the /volume endpoint - r = requests.put("http://127.0.0.1:{}/conf".format(self.server_eventgen_webport), json={"windbag": {}}) - assert r.status_code == 200 - assert json.loads(r.content) - r = requests.post("http://127.0.0.1:{}/volume".format(self.server_eventgen_webport), json={"perDayVolume": 10}) - assert r.status_code == 200 - assert json.loads(r.content) - r = requests.get("http://127.0.0.1:{}/volume".format(self.server_eventgen_webport)) - assert r.status_code == 200 - output = json.loads(r.content) - assert output == 10.0 - r = requests.post("http://127.0.0.1:{}/volume".format(self.server_eventgen_webport), json={"perDayVolume": 150}) - assert r.status_code == 200 - assert json.loads(r.content) - r = requests.get("http://127.0.0.1:{}/volume".format(self.server_eventgen_webport)) - assert r.status_code == 200 - output = json.loads(r.content) - assert output == 150.0 + """ + This test class is used to test the Docker image published as part of this repo. + Specifically, this is testing: + * Eventgen "controller" API and responses + * Eventgen "server" API and responses + * Eventgen controller/server orchestration + """ + + @classmethod + def setup_class(cls): + # Build the image from scratch + cls.client = APIClient(base_url="unix://var/run/docker.sock") + response = cls.client.build(path=REPO_DIR, dockerfile=os.path.join("dockerfiles", "Dockerfile"), tag=IMAGE_NAME, + rm=True, nocache=True, pull=True, stream=False) + for line in response: + print line, + # Create a network for both the controller + server to run in + cls.client.create_network(NETWORK_NAME, driver="bridge", attachable=True) + networking_config = cls.client.create_networking_config({NETWORK_NAME: cls.client.create_endpoint_config()}) + # Start the controller + print 'creating controller' + host_config = cls.client.create_host_config(auto_remove=True, publish_all_ports=True) + container = cls.client.create_container(image=IMAGE_NAME, command="controller", host_config=host_config, + networking_config=networking_config) + cls.client.start(container["Id"]) + TestEventgenOrchestration.controller_id = container["Id"] + print container["Id"] + cls.controller_container = cls.client.inspect_container(container["Id"]) + cls.controller_eventgen_webport = cls.controller_container["NetworkSettings"]["Ports"]["9500/tcp"][0][ + "HostPort"] + cls.controller_rabbitmq_webport = cls.controller_container["NetworkSettings"]["Ports"]["15672/tcp"][0][ + "HostPort"] + # Start the server + print 'creating server' + container = cls.client.create_container( + image=IMAGE_NAME, command="server", environment=[ + "EVENTGEN_AMQP_HOST={}".format(cls.controller_container["Id"][:12])], host_config=host_config, + networking_config=networking_config) + cls.client.start(container["Id"]) + TestEventgenOrchestration.server_id = container["Id"] + print container["Id"] + cls.server_container = cls.client.inspect_container(container["Id"]) + cls.server_eventgen_webport = cls.server_container["NetworkSettings"]["Ports"]["9500/tcp"][0]["HostPort"] + cls.server_rabbitmq_webport = cls.server_container["NetworkSettings"]["Ports"]["15672/tcp"][0]["HostPort"] + # Wait for the controller to be available + print "Waiting for Eventgen Controller to become available." + wait_for_response("http://127.0.0.1:{}".format(cls.controller_eventgen_webport)) + print "Eventgen Controller has become available." + # Wait for the server to be available + print "Waiting for Eventgen Server to become available." + wait_for_response("http://127.0.0.1:{}".format(cls.server_eventgen_webport)) + print "Eventgen Server has become available." + time.sleep(60) + + @classmethod + def teardown_class(cls): + cls.client.remove_container(cls.server_container, v=True, force=True) + cls.client.remove_container(cls.controller_container, v=True, force=True) + cls.client.remove_image(IMAGE_NAME, force=True, noprune=False) + cls.client.remove_network(NETWORK_NAME) + + # Controller tests # + + def test_controller_rabbitmq(self): + r = requests.get("http://127.0.0.1:{}".format(self.controller_rabbitmq_webport)) + assert r.status_code == 200 + assert "RabbitMQ" in r.content + + def test_controller_root(self): + r = requests.get("http://127.0.0.1:{}".format(self.controller_eventgen_webport)) + assert r.status_code == 200 + assert "Eventgen Controller" in r.content + assert "Host: " in r.content + assert "You are running Eventgen Controller" in r.content + + def test_controller_index(self): + r = requests.get("http://127.0.0.1:{}/index".format(self.controller_eventgen_webport)) + assert r.status_code == 200 + assert "Eventgen Controller" in r.content + assert "Host: " in r.content + assert "You are running Eventgen Controller" in r.content + + def test_controller_status(self): + max_retry = 5 + current_retry = 1 + output = {} + while not output and current_retry <= max_retry: + response = requests.get("http://127.0.0.1:{}/status".format(self.controller_eventgen_webport), timeout=10) + if response.status_code == 200: + output = json.loads(response.content) + current_retry += 1 + time.sleep(10) + assert output + + def test_controller_start(self): + r = requests.post("http://127.0.0.1:{}/start".format(self.controller_eventgen_webport)) + assert r.status_code == 200 + assert "Start event dispatched to all" in r.content + + def test_controller_start_with_target(self): + r = requests.post("http://127.0.0.1:{}/start/{}".format(self.controller_eventgen_webport, + TestEventgenOrchestration.server_id[:12])) + assert r.status_code == 200 + assert "Start event dispatched to {}".format(TestEventgenOrchestration.server_id[:12]) in r.content + + def test_controller_stop(self): + r = requests.post("http://127.0.0.1:{}/stop".format(self.controller_eventgen_webport)) + assert r.status_code == 200 + assert "Stop event dispatched to all" in r.content + + def test_controller_stop_with_target(self): + r = requests.post("http://127.0.0.1:{}/stop/{}".format(self.controller_eventgen_webport, + TestEventgenOrchestration.server_id[:12])) + assert r.status_code == 200 + assert "Stop event dispatched to {}".format(TestEventgenOrchestration.server_id[:12]) in r.content + + def test_controller_restart(self): + r = requests.post("http://127.0.0.1:{}/stop".format(self.controller_eventgen_webport)) + assert r.status_code == 200 + assert "Stop event dispatched to all" in r.content + + def test_controller_restart_with_target(self): + r = requests.post("http://127.0.0.1:{}/stop/{}".format(self.controller_eventgen_webport, + TestEventgenOrchestration.server_id[:12])) + assert r.status_code == 200 + assert "Stop event dispatched to {}".format(TestEventgenOrchestration.server_id[:12]) in r.content + + def test_controller_bundle_invalid_request(self): + r = requests.post("http://127.0.0.1:{}/bundle".format(self.controller_eventgen_webport)) + assert r.status_code == 400 + assert "Please pass in a valid object with bundle URL" in r.content + + def test_controller_bundle_with_url(self): + r = requests.post("http://127.0.0.1:{}/bundle".format(self.controller_eventgen_webport), json={ + "url": "http://server.com/bundle.tgz"}) + assert r.status_code == 200 + assert "Bundle event dispatched to all with url http://server.com/bundle.tgz" in r.content + + def test_controller_bundle_with_url_and_target(self): + r = requests.post( + "http://127.0.0.1:{}/bundle/{}".format(self.controller_eventgen_webport, + TestEventgenOrchestration.server_id[:12]), json={ + "url": "http://server.com/bundle.tgz"}) + assert r.status_code == 200 + assert "Bundle event dispatched to {} with url http://server.com/bundle.tgz".format( + TestEventgenOrchestration.server_id[:12]) in r.content + + @pytest.mark.skip(reason="Change in implementation") + def test_controller_get_volume(self): + max_retry = 5 + current_retry = 1 + output = {} + while not output and current_retry <= max_retry: + response = requests.get("http://127.0.0.1:{}/volume".format(self.controller_eventgen_webport), timeout=10) + if response.status_code == 200: + output = json.loads(response.content) + current_retry += 1 + time.sleep(10) + assert output[TestEventgenOrchestration.server_id[:12]] == 0.0 + + def test_controller_set_volume_invalid_request(self): + r = requests.post("http://127.0.0.1:{}/volume".format(self.controller_eventgen_webport)) + assert r.status_code == 400 + assert "Please pass in a valid object with volume" in r.content + + def test_controller_set_volume_with_volume(self): + r = requests.post("http://127.0.0.1:{}/volume".format(self.controller_eventgen_webport), json={ + "perDayVolume": 10}) + assert r.status_code == 200 + assert "set_volume event dispatched to all" in r.content + + def test_controller_set_volume_with_volume_and_target(self): + r = requests.post( + "http://127.0.0.1:{}/volume/{}".format(self.controller_eventgen_webport, + TestEventgenOrchestration.server_id[:12]), json={"perDayVolume": 10}) + assert r.status_code == 200 + assert "set_volume event dispatched to {}".format(TestEventgenOrchestration.server_id[:12]) in r.content + + # Server tests # + + def test_server_root(self): + r = requests.get("http://127.0.0.1:{}".format(self.server_eventgen_webport)) + assert r.status_code == 200 + assert "Host: " in r.content + assert "Eventgen Status" in r.content + assert "Eventgen Config file path" in r.content + assert "Total volume:" in r.content + assert "Worker Queue Status" in r.content + assert "Sample Queue Status" in r.content + assert "Output Queue Status" in r.content + + def test_server_index(self): + r = requests.get("http://127.0.0.1:{}/index".format(self.server_eventgen_webport)) + assert r.status_code == 200 + assert "Host: " in r.content + assert "Eventgen Status" in r.content + assert "Eventgen Config file path" in r.content + assert "Total volume:" in r.content + assert "Worker Queue Status" in r.content + assert "Sample Queue Status" in r.content + assert "Output Queue Status" in r.content + + def test_server_status(self): + r = requests.get("http://127.0.0.1:{}/status".format(self.server_eventgen_webport)) + assert r.status_code == 200 + output = json.loads(r.content) + assert output + assert output['EVENTGEN_STATUS'] == 0 + + def test_server_get_and_set_conf(self): + r = requests.get("http://127.0.0.1:{}/conf".format(self.server_eventgen_webport)) + assert r.status_code == 200 + assert json.loads(r.content) == {} + config_json = {"windbag": {"outputMode": "stdout"}} + r = requests.post("http://127.0.0.1:{}/conf".format(self.server_eventgen_webport), json=config_json) + assert r.status_code == 200 + assert json.loads(r.content) == config_json + + def test_server_start(self): + r = requests.post("http://127.0.0.1:{}/start".format(self.server_eventgen_webport), timeout=5) + assert r.status_code == 200 + assert json.loads(r.content) == "Eventgen has successfully started." + + def test_server_restart(self): + r = requests.post("http://127.0.0.1:{}/restart".format(self.server_eventgen_webport)) + assert r.status_code == 200 + assert json.loads(r.content) == "Eventgen restarted." + + def test_server_stop(self): + r = requests.post("http://127.0.0.1:{}/stop".format(self.server_eventgen_webport)) + assert r.status_code == 200 + assert json.loads(r.content) == "Eventgen is stopped." + + def test_server_bundle(self): + r = requests.post("http://127.0.0.1:{}/bundle".format(self.server_eventgen_webport)) + assert r.status_code == 400 + assert "Please pass in a valid object with bundle URL" in r.content + + def test_server_get_and_set_volume(self): + # Must initialize a stanza with the perDayVolume setting before hitting the /volume endpoint + r = requests.put("http://127.0.0.1:{}/conf".format(self.server_eventgen_webport), json={"windbag": {}}) + assert r.status_code == 200 + assert json.loads(r.content) + r = requests.post("http://127.0.0.1:{}/volume".format(self.server_eventgen_webport), json={"perDayVolume": 10}) + assert r.status_code == 200 + assert json.loads(r.content) + r = requests.get("http://127.0.0.1:{}/volume".format(self.server_eventgen_webport)) + assert r.status_code == 200 + output = json.loads(r.content) + assert output == 10.0 + r = requests.post("http://127.0.0.1:{}/volume".format(self.server_eventgen_webport), json={"perDayVolume": 150}) + assert r.status_code == 200 + assert json.loads(r.content) + r = requests.get("http://127.0.0.1:{}/volume".format(self.server_eventgen_webport)) + assert r.status_code == 200 + output = json.loads(r.content) + assert output == 150.0 diff --git a/tests/large/test_mode_replay.py b/tests/large/test_mode_replay.py new file mode 100644 index 00000000..b58c8f51 --- /dev/null +++ b/tests/large/test_mode_replay.py @@ -0,0 +1,61 @@ +from datetime import datetime +import re +import time +import pytest + + +def test_mode_replay(eventgen_test_helper): + """Test normal replay mode settings""" + events = eventgen_test_helper('eventgen_replay.conf').get_events() + # assert the event length is the same as sample file size + assert len(events) == 12 + pattern = re.compile(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}") + for event in events: + # assert that integer token is replaced + assert "@@integer" not in event + result = pattern.match(event) + assert result is not None + + +def test_mode_replay_end_1(eventgen_test_helper): + """Test normal replay mode with end = 2 which will replay the sample twice and exit""" + events = eventgen_test_helper('eventgen_replay_end_1.conf').get_events() + # assert the event length is twice of the events in the sample file + assert len(events) == 24 + + +def test_mode_replay_end_2(eventgen_test_helper): + """Test normal replay mode with end = -1 which will replay the sample forever""" + helper = eventgen_test_helper('eventgen_replay_end_2.conf') + time.sleep(60) + assert helper.is_alive() + + +def test_mode_replay_backfill(eventgen_test_helper): + """Test normal replay mode with backfill = -5s which should be ignore since backfill < interval""" + events = eventgen_test_helper('eventgen_replay_backfill.conf').get_events() + # assert the events length is twice of the events in the sample file + assert len(events) == 24 + + +@pytest.mark.skip(reason="this issue is not fixed") +def test_mode_replay_timemultiple(eventgen_test_helper): + """Test normal replay mode with timeMultiple = 0.5 which will replay the sample with half time interval""" + current_datetime = datetime.now() + events = eventgen_test_helper('eventgen_replay_timeMultiple.conf').get_events() + + pattern = re.compile(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}") + for event in events: + result = pattern.match(event) + assert result is not None + event_datetime = datetime.strptime(result.group(), "%Y-%m-%d %H:%M:%S") + delter_seconds = (event_datetime - current_datetime).total_seconds() + # assert the event time is after (now - earliest) time + assert delter_seconds < 11 + + +def test_mode_replay_csv(eventgen_test_helper): + """Test normal replay mode with sampletype = csv which will get _raw row from the sample""" + events = eventgen_test_helper('eventgen_replay_csv.conf').get_events() + # assert the events equals to the sample csv file + assert len(events) == 10 diff --git a/tests/large/test_mode_sample.py b/tests/large/test_mode_sample.py new file mode 100644 index 00000000..e7d1575f --- /dev/null +++ b/tests/large/test_mode_sample.py @@ -0,0 +1,101 @@ +from datetime import datetime +import re + + +def test_mode_sample(eventgen_test_helper): + """Test normal sample mode with sampletype = raw""" + current_datetime = datetime.now() + events = eventgen_test_helper("eventgen_sample.conf").get_events() + # assert the event length is the same as sample file size when end = 1 + assert len(events) == 12 + pattern = re.compile(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}") + for event in events: + # assert that integer token is replaced + assert "@@integer" not in event + result = pattern.match(event) + assert result is not None + event_datetime = datetime.strptime(result.group(), "%Y-%m-%d %H:%M:%S") + delter_seconds = (event_datetime - current_datetime).total_seconds() + # assert the event time is after (now - earliest) time + assert delter_seconds > -20 + + +def test_mode_sample_csv(eventgen_test_helper): + """Test normal sample mode with sampletype = csv""" + events = eventgen_test_helper("eventgen_sample_csv.conf").get_events() + # assert the event length is the same as sample file size when end = 1 + assert len(events) == 10 + + +def test_mode_sample_interval(eventgen_test_helper): + """Test normal sample mode with interval = 10s""" + events = eventgen_test_helper("eventgen_sample_interval.conf", timeout=30).get_events() + # assert the total events count is 12 * 3 + assert len(events) == 36 + + +def test_mode_sample_end(eventgen_test_helper): + """Test normal sample mode with end = 1 and outputMode = file which will generate from the sample once""" + helper = eventgen_test_helper("eventgen_sample_end.conf") + events = helper.get_events() + # assert the event length is the same as sample file size when end = 1 + assert len(events) == 12 + + +def test_mode_sample_backfill(eventgen_test_helper): + """Test normal sample mode with end = 1 and backfill = -15s which will generate from the sample once""" + current_datetime = datetime.now() + helper = eventgen_test_helper("eventgen_sample_backfill.conf") + events = helper.get_events() + pattern = re.compile(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}") + for event in events: + result = pattern.match(event) + assert result is not None + event_datetime = datetime.strptime(result.group(), "%Y-%m-%d %H:%M:%S") + delter_seconds = (event_datetime - current_datetime).total_seconds() + # assert the event time is after (now - backfill) time + assert delter_seconds > -15 + + +def test_mode_sample_breaker(eventgen_test_helper): + r"""Test sample mode with end = 1, count = 3 and breaker = ^\d{14}\.\d{6}""" + helper = eventgen_test_helper("eventgen_sample_breaker.conf") + events = helper.get_events() + assert len(events) == 3 + + +def test_mode_sample_earliest(eventgen_test_helper): + """Test sample mode with earliest = -15s""" + current_datetime = datetime.now() + helper = eventgen_test_helper("eventgen_sample_earliest.conf") + events = helper.get_events() + pattern = re.compile(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}") + for event in events: + result = pattern.match(event) + assert result is not None + event_datetime = datetime.strptime(result.group(), "%Y-%m-%d %H:%M:%S") + delter_seconds = (event_datetime - current_datetime).total_seconds() + # assert the event time is after (now - earliest) + 1 time, plus 1 to make it less flaky + assert delter_seconds > -16 + + +def test_mode_sample_latest(eventgen_test_helper): + """Test sample mode with latest = +15s""" + current_datetime = datetime.now() + helper = eventgen_test_helper("eventgen_sample_latest.conf") + events = helper.get_events() + pattern = re.compile(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}") + for event in events: + result = pattern.match(event) + assert result is not None + event_datetime = datetime.strptime(result.group(), "%Y-%m-%d %H:%M:%S") + delter_seconds = (event_datetime - current_datetime).total_seconds() + # assert the event time is after (now - earliest) time + assert delter_seconds < 16 + + +def test_mode_sample_count(eventgen_test_helper): + """Test sample mode with count = 5 which will output 5 events""" + helper = eventgen_test_helper("eventgen_sample_count.conf") + events = helper.get_events() + assert len(events) == 5 diff --git a/tests/large/test_token_replacement.py b/tests/large/test_token_replacement.py new file mode 100644 index 00000000..c602c291 --- /dev/null +++ b/tests/large/test_token_replacement.py @@ -0,0 +1,68 @@ +import json +import os +import csv +import re + +base_dir = os.path.dirname(os.path.abspath(__file__)) + + +def test_token_replacement(eventgen_test_helper): + """Test token replcement with replacementType= static | random | file | timestamp""" + events = eventgen_test_helper("eventgen_token_replacement.conf").get_events() + # assert the events size is 10 since end = 1 + assert len(events) == 10 + + with open(os.path.join(base_dir, 'sample', 'id.csv'), 'rb') as f: + id_content = f.read() + with open(os.path.join(base_dir, 'sample', 'ip.csv'), 'rb') as f: + ip_content = f.read() + with open(os.path.join(base_dir, 'sample', 'cp.csv'), 'rb') as f: + cp_content = f.read() + with open(os.path.join(base_dir, 'sample', 'city.csv'), 'rb') as f: + reader = csv.reader(f) + country = [] + city = [] + latitude = [] + longitude = [] + for row in reader: + country.append(row[0]) + city.append(row[1]) + latitude.append(row[3]) + longitude.append(row[4]) + + integer_id_seed = 1 + for event in events: + try: + event_obj = json.loads(event) + except ValueError: + raise Exception("Token replacement error") + + # assert replacementType = integerid + assert int(event_obj["ppcustomdata"]["receiver_id"]) == integer_id_seed + integer_id_seed += 1 + + # assert replacementType = file + assert event_obj["id"] in id_content + assert event_obj["cp"] in cp_content + assert event_obj["message"]["cliIP"] in ip_content + + # assert replacementType = static + assert event_obj["netPerf"]["lastByte"] == "0" + + # assert replacementType = random and replacement = integer[:] + assert 5000 > int(event_obj["message"]["bytes"]) > 40 + + # assert replacementType = random and replacement = ipv4 | ipv6 | mac + ipv4_pattern = re.compile(r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$") + ipv6_pattern = re.compile(r"^([A-Fa-f0-9]{1,4}:){7}[A-Fa-f0-9]{1,4}$") + mac_pattern = re.compile(r"^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$") + + assert ipv4_pattern.match(event_obj["akadebug"]["Ak_IP"]) is not None + assert ipv6_pattern.match(event_obj["akadebug"]["forward-origin-ip"]) is not None + assert mac_pattern.match(event_obj["akadebug"]["end-user-ip"]) is not None + + # assert replacementType = file | mvfile and replacement = : + assert event_obj["geo"]["city"] in city + assert event_obj["geo"]["country"] in country + assert event_obj["geo"]["lat"] in latitude + assert event_obj["geo"]["long"] in longitude diff --git a/tests/large/utils/__init__.py b/tests/large/utils/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/large/utils/eventgen_test_helper.py b/tests/large/utils/eventgen_test_helper.py new file mode 100644 index 00000000..c53a04e6 --- /dev/null +++ b/tests/large/utils/eventgen_test_helper.py @@ -0,0 +1,77 @@ +import os +import subprocess +import re +from threading import Timer + +import configparser + +# $EVENTGEN_HOME/tests/large +base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +# change working directory so that 'splunk_eventgen' call in the project root directory +os.chdir(os.path.dirname(os.path.dirname(base_dir))) + + +class EventgenTestHelper(object): + def __init__(self, conf, timeout=None): + self.conf = os.path.join(base_dir, 'conf', conf) + self.config, self.section = self._read_conf(self.conf) + self.output_mode = self._get_output_mode() + self.file_name = self._get_file_name() + self.breaker = self._get_breaker() + self.process = subprocess.Popen(['splunk_eventgen', 'generate', self.conf], stdout=subprocess.PIPE) + if timeout: + timer = Timer(timeout, self.kill) + timer.start() + + def kill(self): + self.process.kill() + + def is_alive(self): + if self.process.poll() is None: + return True + else: + return False + + def get_events(self): + """Get events either from stdout or from file""" + self.process.wait() + if self.output_mode == 'stdout': + output = self.process.communicate()[0] + elif self.output_mode == 'file': + with open(os.path.join(base_dir, 'results', self.file_name), 'r') as f: + output = f.read() + + if self.breaker[0] == '^': + self.breaker = self.breaker[1:] + if self.breaker[-1] == '$': + self.breaker = self.breaker[:-1] + results = re.split(self.breaker, output) + return [x for x in results if x != ""] + + def tear_down(self): + """Kill sub-processes and remove results file""" + if self.is_alive(): + self.process.kill() + if self.file_name: + os.remove(os.path.join(base_dir, 'results', self.file_name)) + + def _get_output_mode(self): + return self.config.get(self.section, 'outputMode', fallback=None) + + def _get_file_name(self): + file_name = None + file_name_value = self.config.get(self.section, 'fileName', fallback=None) + if file_name_value is not None: + file_name = file_name_value.split(os.sep)[-1] + return file_name + + def _get_breaker(self): + return self.config.get(self.section, 'breaker', fallback='\n') + + @staticmethod + def _read_conf(conf): + config = configparser.ConfigParser() + config.read(conf) + if len(config.sections()) != 1 or config.sections()[0] == 'default' or config.sections()[0] == 'global': + raise Exception("Invalid test eventgen conf") + return config, config.sections()[0] diff --git a/tests/medium/plugins/test_file_output.py b/tests/medium/plugins/test_file_output.py index d1b7a92a..f290f640 100644 --- a/tests/medium/plugins/test_file_output.py +++ b/tests/medium/plugins/test_file_output.py @@ -3,7 +3,9 @@ import os import sys + from mock import patch + from splunk_eventgen.__main__ import parse_args from splunk_eventgen.eventgen_core import EventGenerator @@ -11,7 +13,6 @@ class TestFileOutputPlugin(object): - def test_output_data_to_file(self): configfile = "tests/sample_eventgen_conf/medium_test/eventgen.conf.fileoutput" testargs = ["eventgen", "generate", configfile] diff --git a/tests/medium/plugins/test_jinja_generator.py b/tests/medium/plugins/test_jinja_generator.py index beab0b82..0bb7bd96 100644 --- a/tests/medium/plugins/test_jinja_generator.py +++ b/tests/medium/plugins/test_jinja_generator.py @@ -1,5 +1,6 @@ import os import sys + from mock import patch from splunk_eventgen.__main__ import parse_args from splunk_eventgen.eventgen_core import EventGenerator @@ -9,7 +10,7 @@ class TestJinjaGenerator(object): - + def test_jinja_generator_to_file(self): configfile = "tests/sample_eventgen_conf/jinja/eventgen.conf.jinja_basic" testargs = ["eventgen", "generate", configfile] diff --git a/tests/medium/plugins/test_syslog_output.py b/tests/medium/plugins/test_syslog_output.py index eb5b8c45..831296c4 100644 --- a/tests/medium/plugins/test_syslog_output.py +++ b/tests/medium/plugins/test_syslog_output.py @@ -3,7 +3,9 @@ import os import sys + from mock import MagicMock, patch + from splunk_eventgen.__main__ import parse_args from splunk_eventgen.eventgen_core import EventGenerator from splunk_eventgen.lib.plugins.output.syslogout import SyslogOutOutputPlugin @@ -12,12 +14,11 @@ class TestSyslogOutputPlugin(object): - def test_output_data_to_syslog(self): configfile = "tests/sample_eventgen_conf/medium_test/eventgen.conf.syslogoutput" testargs = ["eventgen", "generate", configfile] with patch.object(sys, 'argv', testargs): - with patch('logging.getLogger') as mock_log: + with patch('logging.getLogger'): pargs = parse_args() assert pargs.subcommand == 'generate' assert pargs.configfile == configfile diff --git a/tests/medium/plugins/test_tcp_output.py b/tests/medium/plugins/test_tcp_output.py index e62ecdaa..e3ea1320 100644 --- a/tests/medium/plugins/test_tcp_output.py +++ b/tests/medium/plugins/test_tcp_output.py @@ -3,7 +3,9 @@ import os import sys + from mock import MagicMock, patch + from splunk_eventgen.__main__ import parse_args from splunk_eventgen.eventgen_core import EventGenerator from splunk_eventgen.lib.plugins.output.tcpout import TcpOutputPlugin @@ -12,7 +14,6 @@ class TestTcpOutputPlugin(object): - def test_output_data_to_tcp_port(self): configfile = "tests/sample_eventgen_conf/medium_test/eventgen.conf.tcpoutput" testargs = ["eventgen", "generate", configfile] @@ -35,4 +36,3 @@ def test_output_data_to_tcp_port(self): eventgen.start() tcpoutput.s.connect.assert_called_with(('127.0.0.1', 9999)) assert tcpoutput.s.send.call_count == 5 - diff --git a/tests/medium/plugins/test_udp_output.py b/tests/medium/plugins/test_udp_output.py index aec78fa6..a7cbde26 100644 --- a/tests/medium/plugins/test_udp_output.py +++ b/tests/medium/plugins/test_udp_output.py @@ -3,7 +3,9 @@ import os import sys + from mock import MagicMock, patch + from splunk_eventgen.__main__ import parse_args from splunk_eventgen.eventgen_core import EventGenerator from splunk_eventgen.lib.plugins.output.udpout import UdpOutputPlugin @@ -12,7 +14,6 @@ class TestUdpOutputPlugin(object): - def test_output_data_to_udp_port(self): configfile = "tests/sample_eventgen_conf/medium_test/eventgen.conf.udpoutput" testargs = ["eventgen", "generate", configfile] diff --git a/tests/run_tests.py b/tests/run_tests.py index 871c29c2..8d433456 100644 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -1,7 +1,8 @@ -import pytest -import sys -import time import os +import sys + +import pytest + SMALL = 'tests/small' MEDIUM = 'tests/medium' LARGE = 'tests/large' @@ -11,13 +12,12 @@ ENV = os.environ PATH = sys.path -# Set to 1 is debugging is a problem. Normally, it is 8, which should match the cores/hyperthreads of most of our systems. +# Normally, it is 8, which should match the cores/hyperthreads of most of our systems. NUM_TEST_WORKERS_LARGE = '8' - """ How to run the tests: 1. python run_tests.py -2. python run_tests.py {SMALL_TESTS_TO_RUN} {MEDIUM_TESTS_TO_RUN} {LARGE_TESTS_TO_RUN} {XLARGE_TESTS_TO_RUN} {optional RUN_DESTROY} +2. python run_tests.py {SMALL_TEST_PATH} {MEDIUM_TEST_PATH} {LARGE_TEST_PATH} {XLARGE_TEST_PATH} {optional RUN_DESTROY} - You can pass 'None' as a value to either to ignore those tests - To run a specific folder, file, pass it in as a value. ex * python run_tests.py None None tests/large/test_destroy.py None @@ -46,7 +46,9 @@ if SMALL: sys.path = PATH os.environ = ENV - args = [ "--cov=splunk_eventgen", "--cov-config=tests/.coveragerc", "--cov-report=term", "--cov-report=html", SMALL, "--junitxml=tests/test-reports/tests_small_results.xml"] + args = [ + "--cov=splunk_eventgen", "--cov-config=tests/.coveragerc", "--cov-report=term", "--cov-report=html", SMALL, + "--junitxml=tests/test-reports/tests_small_results.xml"] return_codes.append(pytest.main(args)) # Run medium tests diff --git a/tests/sample_eventgen_conf/unit/eventgen.conf.config b/tests/sample_eventgen_conf/unit/eventgen.conf.config new file mode 100644 index 00000000..81f3c44e --- /dev/null +++ b/tests/sample_eventgen_conf/unit/eventgen.conf.config @@ -0,0 +1,38 @@ +[sample] +sampleDir = tests/sample_eventgen_conf/sample +outputMode = splunkstream +splunkMethod = https +splunkHost = localhost +splunkPort = 8088 +earliest = -3s +latest = now + +count = -1 +delay = 10 +interval = 3 + +perDayVolume = 1 +randomizeCount = 0.2 +timeMultiple = 2 + +disabled = false +profiler = false +useOutputQueue = false +bundlelines = false +httpeventWaitResponse = false +sequentialTimestamp = false +autotimestamp = false +randomizeEvents = false +outputCounter = false + +minuteOfHourRate = { "0": 1, "1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "6": 1, "7": 1, "8": 1, "9": 1, "10": 1, "11": 1, "12": 1, "13": 1, "14": 1, "15": 1, "16": 1, "17": 1, "18": 1, "19": 1, "20": 1, "21": 1, "22": 1, "23": 1, "24": 1, "25": 1, "26": 1, "27": 1, "28": 1, "29": 1, "30": 1, "31": 1, "32": 1, "33": 1, "34": 1, "35": 4, "36": 0.1, "37": 0.1, "38": 1, "39": 1, "40": 1, "41": 1, "42": 1, "43": 1, "44": 1, "45": 1, "46": 1, "47": 1, "48": 1, "49": 1, "50": 1, "51": 1, "52": 1, "53": 1, "54": 1, "55": 1, "56": 1, "57": 1, "58": 1, "59": 1 } +hourOfDayRate = { "0": 0.30, "1": 0.20, "2": 0.20, "3": 0.20, "4": 0.20, "5": 0.25, "6": 0.35, "7": 0.50, "8": 0.60, "9": 0.65, "10": 0.70, "11": 0.75, "12": 0.77, "13": 0.80, "14": 0.82, "15": 0.85, "16": 0.87, "17": 0.90, "18": 0.95, "19": 1.0, "20": 0.85, "21": 0.70, "22": 0.60, "23": 0.45 } +dayOfWeekRate = { "0": 0.97, "1": 0.95, "2": 0.90, "3": 0.97, "4": 1.0, "5": 0.99, "6": 0.55 } +dayOfMonthRate = { "1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "6": 1, "7": 1, "8": 1, "9": 1, "10": 1, "11": 1, "12": 1, "13": 1, "14": 1, "15": 1, "16": 1, "17": 1, "18": 1, "19": 1, "20": 1, "21": 1, "22": 1, "23": 1, "24": 1, "25": 1, "26": 1, "27": 1, "28": 1, "29": 1, "30": 1, "31": 1 } +monthOfYearRate = { "1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "6": 1, "7": 1, "8": 1, "9": 1, "10": 1, "11": 1, "12": 1 } +httpeventServers = {"servers":[{ "protocol":"https", "address":"127.0.0.1", "port":"8088", "key":"8d5ab52c-3759-49e3-b66a-5213ce525692"}]} +autotimestamps = [["\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}", "%Y-%m-%d %H:%M:%S"], ["\\d{1,2}\\/\\w{3}\\/\\d{4}\\s\\d{2}:\\d{2}:\\d{2}:\\d{1,3}", "%d/%b/%Y %H:%M:%S:%f"], ["\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}", "%Y-%m-%dT%H:%M:%S.%f"], ["\\d{1,2}/\\w{3}/\\d{4}\\s\\d{2}:\\d{2}:\\d{2}:\\d{1,3}", "%d/%b/%Y %H:%M:%S:%f"], ["\\d{1,2}/\\d{2}/\\d{2}\\s\\d{1,2}:\\d{2}:\\d{2}", "%m/%d/%y %H:%M:%S"], ["\\d{2}-\\d{2}-\\d{4} \\d{2}:\\d{2}:\\d{2}", "%m-%d-%Y %H:%M:%S"], ["\\w{3} \\w{3} +\\d{1,2} \\d{2}:\\d{2}:\\d{2}", "%a %b %d %H:%M:%S"], ["\\w{3} \\w{3} \\d{2} \\d{4} \\d{2}:\\d{2}:\\d{2}", "%a %b %d %Y %H:%M:%S"], ["^(\\w{3}\\s+\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2})", "%b %d %H:%M:%S"], ["(\\w{3}\\s+\\d{1,2}\\s\\d{1,2}:\\d{1,2}:\\d{1,2})", "%b %d %H:%M:%S"], ["(\\w{3}\\s\\d{1,2}\\s\\d{1,4}\\s\\d{1,2}:\\d{1,2}:\\d{1,2})", "%b %d %Y %H:%M:%S"], ["\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}", "%Y-%m-%d %H:%M:%S.%f"], ["\\,\\d{2}\\/\\d{2}\\/\\d{2,4}\\s+\\d{2}:\\d{2}:\\d{2}\\s+[AaPp][Mm]\\,", ",%m/%d/%Y %I:%M:%S %p,"], ["^\\w{3}\\s+\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}", "%b %d %H:%M:%S"], ["\\d{2}/\\d{2}/\\d{4} \\d{2}:\\d{2}:\\d{2}", "%m/%d/%Y %H:%M:%S"], ["^\\d{2}\\/\\d{2}\\/\\d{2,4}\\s+\\d{2}:\\d{2}:\\d{2}\\s+[AaPp][Mm]", "%m/%d/%Y %I:%M:%S %p"], ["\\d{2}\\/\\d{2}\\/\\d{4}\\s\\d{2}:\\d{2}:\\d{2}", "%m-%d-%Y %H:%M:%S"], ["\\\"timestamp\\\":\\s\\\"(\\d+)", "%s"], ["\\d{2}\\/\\w+\\/\\d{4}\\s\\d{2}:\\d{2}:\\d{2}:\\d{3}", "%d-%b-%Y %H:%M:%S:%f"], ["\\\"created\\\":\\s(\\d+)", "%s"], ["\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}", "%Y-%m-%dT%H:%M:%S"], ["\\d{1,2}/\\w{3}/\\d{4}:\\d{2}:\\d{2}:\\d{2}:\\d{1,3}", "%d/%b/%Y:%H:%M:%S:%f"], ["\\d{1,2}/\\w{3}/\\d{4}:\\d{2}:\\d{2}:\\d{2}", "%d/%b/%Y:%H:%M:%S"]] + +token.0.token = \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} +token.0.replacementType = timestamp +token.0.replacement = %Y-%m-%d %H:%M:%S diff --git a/tests/small/test_main.py b/tests/small/test_main.py index 6dda5007..3f68254d 100644 --- a/tests/small/test_main.py +++ b/tests/small/test_main.py @@ -1,23 +1,25 @@ #!/usr/bin/env python2 -import pytest import os import sys -from mock import MagicMock, call, patch, mock_open + +import pytest +from mock import MagicMock, patch + +from splunk_eventgen.__main__ import parse_cli_vars, parse_env_vars FILE_DIR = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, os.path.join(FILE_DIR, "..", "..", "..")) sys.path.insert(0, os.path.join(FILE_DIR, "..", "..", "..", "splunk_eventgen")) -from splunk_eventgen.__main__ import parse_cli_vars, parse_env_vars -@pytest.mark.parametrize(('config'), - [ - # Empty config - ({}), - # Some elements already defined - function should override - ({"AMQP_HOST": "guest", "AMQP_PASS": "guest"}) - ]) +@pytest.mark.parametrize( + ('config'), + [ + # Empty config + ({}), + # Some elements already defined - function should override + ({"AMQP_HOST": "guest", "AMQP_PASS": "guest"})]) def test_parse_cli_vars(config): args = MagicMock() args.amqp_uri = "pyamqp://user:pass@host:port" @@ -28,32 +30,34 @@ def test_parse_cli_vars(config): args.amqp_pass = "world" args.web_server_address = "0.0.0.:1111" obj = parse_cli_vars(config, args) - assert obj == { "AMQP_URI": "pyamqp://user:pass@host:port", - "AMQP_HOST": "hostname", - "AMQP_PORT": 8001, - "AMQP_WEBPORT": 8000 , - "AMQP_USER": "hello", - "AMQP_PASS": "world", - "WEB_SERVER_ADDRESS": "0.0.0.:1111" } + assert obj == { + "AMQP_URI": "pyamqp://user:pass@host:port", "AMQP_HOST": "hostname", "AMQP_PORT": 8001, "AMQP_WEBPORT": 8000, + "AMQP_USER": "hello", "AMQP_PASS": "world", "WEB_SERVER_ADDRESS": "0.0.0.:1111"} -@pytest.mark.parametrize(('env_vars'), - [ - # No environment vars defined - ({}), - # All environemnt vars defined - ({"EVENTGEN_AMQP_URI": "test", "EVENTGEN_AMQP_HOST": "host", "EVENTGEN_AMQP_PORT": 8000, "EVENTGEN_AMQP_WEBPORT": 8001, "EVENTGEN_AMQP_USER": "hello", "EVENTGEN_AMQP_PASS": "world", "EVENTGEN_WEB_SERVER_ADDR": "0.0.0.0:1111"}) - ]) + +@pytest.mark.parametrize( + ('env_vars'), + [ + # No environment vars defined + ({}), + # All environemnt vars defined + ({ + "EVENTGEN_AMQP_URI": "test", "EVENTGEN_AMQP_HOST": "host", "EVENTGEN_AMQP_PORT": 8000, + "EVENTGEN_AMQP_WEBPORT": 8001, "EVENTGEN_AMQP_USER": "hello", "EVENTGEN_AMQP_PASS": "world", + "EVENTGEN_WEB_SERVER_ADDR": "0.0.0.0:1111"})]) def test_parse_env_vars(env_vars): with patch("splunk_eventgen.__main__.os") as mock_os: mock_os.environ = env_vars obj = parse_env_vars() - assert obj.keys() == ['AMQP_WEBPORT', 'AMQP_USER', 'AMQP_PASS', 'AMQP_PORT', 'AMQP_URI', 'WEB_SERVER_ADDRESS', 'AMQP_HOST'] + assert obj.keys() == [ + 'AMQP_WEBPORT', 'AMQP_USER', 'AMQP_PASS', 'AMQP_PORT', 'AMQP_URI', 'WEB_SERVER_ADDRESS', 'AMQP_HOST'] if env_vars: # If enviroment vars are defined, let's make sure they are set instead of default values assert obj["WEB_SERVER_ADDRESS"] == "0.0.0.0:1111" assert obj["AMQP_HOST"] == "host" assert obj["AMQP_PORT"] == 8000 + def test_parse_env_vars_and_parse_cli_vars(): ''' This test checks the layering effect of both parsing CLI and env vars. @@ -67,7 +71,7 @@ def test_parse_env_vars_and_parse_cli_vars(): assert obj["AMQP_PORT"] == 5672 assert obj["AMQP_PASS"] == "guest" assert obj["AMQP_USER"] == "guest" - assert obj["AMQP_URI"] == None + assert obj["AMQP_URI"] is None assert obj["WEB_SERVER_ADDRESS"] == "0.0.0.0:9500" args = MagicMock() args.amqp_uri = "pyamqp://user:pass@host:port" @@ -78,11 +82,7 @@ def test_parse_env_vars_and_parse_cli_vars(): # Purposely defining None vars here for these CLI args - in this case, environment vars will be used args.amqp_user = None args.amqp_pass = None - newobj = parse_cli_vars(obj, args) - assert obj == { "AMQP_URI": "pyamqp://user:pass@host:port", - "AMQP_HOST": "hostname", - "AMQP_PORT": 8001, - "AMQP_WEBPORT": 8000 , - "AMQP_USER": "guest", - "AMQP_PASS": "guest", - "WEB_SERVER_ADDRESS": "0.0.0.:1111" } + parse_cli_vars(obj, args) + assert obj == { + "AMQP_URI": "pyamqp://user:pass@host:port", "AMQP_HOST": "hostname", "AMQP_PORT": 8001, "AMQP_WEBPORT": + 8000, "AMQP_USER": "guest", "AMQP_PASS": "guest", "WEB_SERVER_ADDRESS": "0.0.0.:1111"} diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py new file mode 100644 index 00000000..528209ef --- /dev/null +++ b/tests/unit/conftest.py @@ -0,0 +1,17 @@ +from os import path as op + +import pytest + +from splunk_eventgen.lib.eventgenconfig import Config + + +@pytest.fixture +def eventgen_config(): + """Returns a function to create config instance based on config file""" + + def _make_eventgen_config_instance(configfile=None): + if configfile is not None: + configfile = op.join(op.dirname(op.dirname(__file__)), 'sample_eventgen_conf', 'unit', configfile) + return Config(configfile=configfile) + + return _make_eventgen_config_instance diff --git a/tests/unit/test_eventgenconfig.py b/tests/unit/test_eventgenconfig.py new file mode 100644 index 00000000..b0391ef6 --- /dev/null +++ b/tests/unit/test_eventgenconfig.py @@ -0,0 +1,277 @@ +import json +import os +from ConfigParser import ConfigParser + +import pytest + +from splunk_eventgen.lib.eventgensamples import Sample + + +def test_makeSplunkEmbedded(eventgen_config): + """Test makeSplunkEmbedded works""" + config_instance = eventgen_config() + session_key = 'ea_IO86v01Xipz8BuB_Ako9rMoc5_HNn6UQrBhVQY5zj68LN2J2xVrLzYD^XEgVTWyKrXva6r8yZ2gtEuv9nnZ' + config_instance.makeSplunkEmbedded(session_key) + assert config_instance.splunkEmbedded + # reset splunkEmbedded since all instances share the attribute + config_instance.splunkEmbedded = False + + +def test_buildConfDict(eventgen_config): + """Test buildConfDict returns the same as reading directly from file""" + config_instance = eventgen_config() + config_instance._buildConfDict() + configparser = ConfigParser() + splunk_eventgen_folder = os.path.join( + os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'splunk_eventgen') + configparser.read(os.path.join(splunk_eventgen_folder, 'default', 'eventgen.conf')) + configparser.set('global', 'eai:acl', {'app': 'splunk_eventgen'}) + + for key, value in config_instance._confDict['global'].items(): + assert value == configparser.get('global', key) + + +def test_validate_setting_count(eventgen_config): + """Test count config is int with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'count', '0')) == int + assert config_instance._validateSetting('sample', 'count', '0') == 0 + + +def test_validate_setting_delay(eventgen_config): + """Test delay config is int with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'delay', '10')) == int + assert config_instance._validateSetting('sample', 'delay', '10') == 10 + + +def test_validate_setting_interval(eventgen_config): + """Test interval config is int with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'interval', '3')) == int + assert config_instance._validateSetting('sample', 'interval', '3') == 3 + + +def test_validate_setting_perdayvolume(eventgen_config): + """Test perdayvolume config is float with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'perDayVolume', '1')) == float + assert config_instance._validateSetting('sample', 'perDayVolume', '1') == 1.0 + + +def test_validate_setting_randomizeCount(eventgen_config): + """Test randomizeCount config is float with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'randomizeCount', '0.2')) == float + assert config_instance._validateSetting('sample', 'randomizeCount', '0.2') == 0.2 + + +def test_validate_setting_timeMultiple(eventgen_config): + """Test timeMultiple config is float with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'timeMultiple', '2')) == float + assert config_instance._validateSetting('sample', 'timeMultiple', '2') == 2.0 + + +def test_validate_setting_disabled(eventgen_config): + """Test disabled config is bool with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'disabled', 'false')) == bool + assert config_instance._validateSetting('sample', 'disabled', 'false') is False + + +def test_validate_setting_profiler(eventgen_config): + """Test profiler config is bool with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'profiler', 'false')) == bool + assert config_instance._validateSetting('sample', 'profiler', 'false') is False + + +def test_validate_setting_useOutputQueue(eventgen_config): + """Test useOutputQueue config is bool with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'useOutputQueue', 'false')) == bool + assert config_instance._validateSetting('sample', 'useOutputQueue', 'false') is False + + +def test_validate_setting_bundlelines(eventgen_config): + """Test bundlelines config is bool with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'bundlelines', 'false')) == bool + assert config_instance._validateSetting('sample', 'bundlelines', 'false') is False + + +def test_validate_setting_httpeventWaitResponse(eventgen_config): + """Test httpeventWaitResponse config is bool with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'httpeventWaitResponse', 'false')) == bool + assert config_instance._validateSetting('sample', 'httpeventWaitResponse', 'false') is False + + +def test_validate_setting_sequentialTimestamp(eventgen_config): + """Test sequentialTimestamp config is bool with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'sequentialTimestamp', 'false')) == bool + assert config_instance._validateSetting('sample', 'sequentialTimestamp', 'false') is False + + +def test_validate_setting_autotimestamp(eventgen_config): + """Test autotimestamp config is bool with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'autotimestamp', 'false')) == bool + assert config_instance._validateSetting('sample', 'autotimestamp', 'false') is False + + +def test_validate_setting_randomizeEvents(eventgen_config): + """Test randomizeEvents config is bool with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'randomizeEvents', 'false')) == bool + assert config_instance._validateSetting('sample', 'randomizeEvents', 'false') is False + + +def test_validate_setting_outputCounter(eventgen_config): + """Test outputCounter config is bool with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert type(config_instance._validateSetting('sample', 'outputCounter', 'false')) == bool + assert config_instance._validateSetting('sample', 'outputCounter', 'false') is False + + +def test_validate_setting_minuteOfHourRate(eventgen_config): + """Test minuteOfHourRate config is dict with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + minuteOfHourRate = '{ "0": 1, "1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "6": 1, "7": 1, "8": 1, "9": 1,' \ + ' "10": 1, "11": 1, "12": 1, "13": 1, "14": 1, "15": 1, "16": 1, "17": 1, "18": 1,' \ + ' "19": 1, "20": 1, "21": 1, "22": 1, "23": 1, "24": 1, "25": 1, "26": 1, "27": 1,' \ + ' "28": 1, "29": 1, "30": 1, "31": 1, "32": 1, "33": 1, "34": 1, "35": 4, "36": 0.1,' \ + ' "37": 0.1, "38": 1, "39": 1, "40": 1, "41": 1, "42": 1, "43": 1, "44": 1, "45": 1,' \ + ' "46": 1, "47": 1, "48": 1, "49": 1, "50": 1, "51": 1, "52": 1, "53": 1, "54": 1,' \ + ' "55": 1, "56": 1, "57": 1, "58": 1, "59": 1 }' + assert type(config_instance._validateSetting('sample', 'minuteOfHourRate', minuteOfHourRate)) == dict + result = json.loads(minuteOfHourRate) + assert config_instance._validateSetting('sample', 'minuteOfHourRate', minuteOfHourRate) == result + + +def test_validate_setting_hourOfDayRate(eventgen_config): + """Test hourOfDayRate config is dict with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + hourOfDayRate = '{ "0": 0.30, "1": 0.20, "2": 0.20, "3": 0.20, "4": 0.20, "5": 0.25, "6": 0.35, "7": 0.50,' \ + ' "8": 0.60, "9": 0.65, "10": 0.70, "11": 0.75, "12": 0.77, "13": 0.80, "14": 0.82,' \ + ' "15": 0.85, "16": 0.87, "17": 0.90, "18": 0.95, "19": 1.0, "20": 0.85, "21": 0.70,' \ + ' "22": 0.60, "23": 0.45 }' + assert type(config_instance._validateSetting('sample', 'hourOfDayRate', hourOfDayRate)) == dict + result = json.loads(hourOfDayRate) + assert config_instance._validateSetting('sample', 'hourOfDayRate', hourOfDayRate) == result + + +def test_validate_setting_dayOfWeekRate(eventgen_config): + """Test dayOfWeekRate config is dict with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + dayOfWeekRate = '{ "0": 0.97, "1": 0.95, "2": 0.90, "3": 0.97, "4": 1.0, "5": 0.99, "6": 0.55 }' + assert type(config_instance._validateSetting('sample', 'dayOfWeekRate', dayOfWeekRate)) == dict + result = json.loads(dayOfWeekRate) + assert config_instance._validateSetting('sample', 'dayOfWeekRate', dayOfWeekRate) == result + + +def test_validate_setting_dayOfMonthRate(eventgen_config): + """Test dayOfMonthRate config is dict with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + dayOfMonthRate = '{ "1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "6": 1, "7": 1, "8": 1, "9": 1, "10": 1,' \ + ' "11": 1, "12": 1, "13": 1, "14": 1, "15": 1, "16": 1, "17": 1, "18": 1, "19": 1, "20": 1,' \ + ' "21": 1, "22": 1, "23": 1, "24": 1, "25": 1, "26": 1, "27": 1, "28": 1, "29": 1, "30": 1,' \ + ' "31": 1 }' + assert type(config_instance._validateSetting('sample', 'dayOfMonthRate', dayOfMonthRate)) == dict + result = json.loads(dayOfMonthRate) + assert config_instance._validateSetting('sample', 'dayOfMonthRate', dayOfMonthRate) == result + + +def test_validate_setting_monthOfYearRate(eventgen_config): + """Test monthOfYearRate config is dict with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + monthOfYearRate = '{ "1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "6": 1, "7": 1,' \ + ' "8": 1, "9": 1, "10": 1, "11": 1, "12": 1 }' + assert type(config_instance._validateSetting('sample', 'monthOfYearRate', monthOfYearRate)) == dict + result = json.loads(monthOfYearRate) + assert config_instance._validateSetting('sample', 'monthOfYearRate', monthOfYearRate) == result + + +def test_validate_setting_httpeventServers(eventgen_config): + """Test httpeventServers config is dict with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + httpeventServers = '{"servers":[{ "protocol":"https", "address":"127.0.0.1",' \ + ' "port":"8088", "key":"8d5ab52c-3759-49e3-b66a-5213ce525692"}]}' + assert type(config_instance._validateSetting('sample', 'httpeventServers', httpeventServers)) == dict + result = json.loads(httpeventServers) + assert config_instance._validateSetting('sample', 'httpeventServers', httpeventServers) == result + + +def test_validate_setting_autotimestamps(eventgen_config): + """Test autotimestamps config is dict with right value""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + autotimestamps = r'[["\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}", "%Y-%m-%d %H:%M:%S"], ' \ + r'["\\d{1,2}\\/\\w{3}\\/\\d{4}\\s\\d{2}:\\d{2}:\\d{2}:\\d{1,3}", "%d/%b/%Y %H:%M:%S:%f"], ' \ + r'["\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}", "%Y-%m-%dT%H:%M:%S.%f"], ' \ + r'["\\d{1,2}/\\w{3}/\\d{4}\\s\\d{2}:\\d{2}:\\d{2}:\\d{1,3}", "%d/%b/%Y %H:%M:%S:%f"], ' \ + r'["\\d{1,2}/\\d{2}/\\d{2}\\s\\d{1,2}:\\d{2}:\\d{2}", "%m/%d/%y %H:%M:%S"], ' \ + r'["\\d{2}-\\d{2}-\\d{4} \\d{2}:\\d{2}:\\d{2}", "%m-%d-%Y %H:%M:%S"], ' \ + r'["\\w{3} \\w{3} +\\d{1,2} \\d{2}:\\d{2}:\\d{2}", "%a %b %d %H:%M:%S"], ' \ + r'["\\w{3} \\w{3} \\d{2} \\d{4} \\d{2}:\\d{2}:\\d{2}", "%a %b %d %Y %H:%M:%S"], ' \ + r'["^(\\w{3}\\s+\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2})", "%b %d %H:%M:%S"], ' \ + r'["(\\w{3}\\s+\\d{1,2}\\s\\d{1,2}:\\d{1,2}:\\d{1,2})", "%b %d %H:%M:%S"], ' \ + r'["(\\w{3}\\s\\d{1,2}\\s\\d{1,4}\\s\\d{1,2}:\\d{1,2}:\\d{1,2})", "%b %d %Y %H:%M:%S"], ' \ + r'["\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}\\.\\d{3}", "%Y-%m-%d %H:%M:%S.%f"], ' \ + r'["\\,\\d{2}\\/\\d{2}\\/\\d{2,4}\\s+\\d{2}:\\d{2}:\\d{2}\\s+[AaPp][Mm]\\,", ' \ + r'",%m/%d/%Y %I:%M:%S %p,"], ' \ + r'["^\\w{3}\\s+\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}", "%b %d %H:%M:%S"], ' \ + r'["\\d{2}/\\d{2}/\\d{4} \\d{2}:\\d{2}:\\d{2}", "%m/%d/%Y %H:%M:%S"], ' \ + r'["^\\d{2}\\/\\d{2}\\/\\d{2,4}\\s+\\d{2}:\\d{2}:\\d{2}\\s+[AaPp][Mm]", "%m/%d/%Y %I:%M:%S %p"],' \ + r'["\\d{2}\\/\\d{2}\\/\\d{4}\\s\\d{2}:\\d{2}:\\d{2}", "%m-%d-%Y %H:%M:%S"], ' \ + r'["\\\"timestamp\\\":\\s\\\"(\\d+)", "%s"], ' \ + r'["\\d{2}\\/\\w+\\/\\d{4}\\s\\d{2}:\\d{2}:\\d{2}:\\d{3}", "%d-%b-%Y %H:%M:%S:%f"], ' \ + r'["\\\"created\\\":\\s(\\d+)", "%s"], ["\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}", ' \ + r'"%Y-%m-%dT%H:%M:%S"], ' \ + r'["\\d{1,2}/\\w{3}/\\d{4}:\\d{2}:\\d{2}:\\d{2}:\\d{1,3}", "%d/%b/%Y:%H:%M:%S:%f"], ' \ + r'["\\d{1,2}/\\w{3}/\\d{4}:\\d{2}:\\d{2}:\\d{2}", "%d/%b/%Y:%H:%M:%S"]]' + assert type(config_instance._validateSetting('sample', 'autotimestamps', autotimestamps)) == list + result = json.loads(autotimestamps) + assert config_instance._validateSetting('sample', 'autotimestamps', autotimestamps) == result + + +def test_getPlugin(eventgen_config): + """Test getPlugin method without loading any plugins""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + with pytest.raises(KeyError): + config_instance.getPlugin('output.awss3') + + +def test_getSplunkUrl(eventgen_config): + """Test getSplunkUrl with provided sample object""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + sample = Sample('test') + sample.splunkHost = 'localhost' + sample.splunkMethod = 'https' + sample.splunkPort = '8088' + + assert ('https://localhost:8088', 'https', 'localhost', '8088') == config_instance.getSplunkUrl(sample) + + +def test_validateTimeZone(eventgen_config): + """Test _validateTimeZone method""" + pass + + +def test_validateSeed(eventgen_config): + """Test _validateSeed method""" + pass + + +def test_punct(eventgen_config): + """Test _punct method with given string""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + assert '--:\n$^' == config_instance._punct('this-is-a: test \ntest $^') + + +def test_parse(eventgen_config): + """Test parse method with given evengen config""" + config_instance = eventgen_config(configfile='eventgen.conf.config') + config_instance.parse() + assert len(config_instance.samples) == 1 diff --git a/tests/unit/test_timeparser.py b/tests/unit/test_timeparser.py new file mode 100644 index 00000000..4dc7d13d --- /dev/null +++ b/tests/unit/test_timeparser.py @@ -0,0 +1,105 @@ +import datetime + +import pytest + +from splunk_eventgen.lib import timeparser + +time_delta_test_params = [(datetime.timedelta(days=1), 86400), + (datetime.timedelta(days=1, hours=3, minutes=15, seconds=32), 98132), + (datetime.timedelta(hours=1, minutes=10), 4200), (datetime.timedelta(hours=-1), -3600), + (None, 0)] + + +@pytest.mark.parametrize('delta,expect', time_delta_test_params) +def test_time_delta_2_second(delta, expect): + ''' Test timeDelta2secs function, convert time delta object to seconds + Normal cases: + case 1: time delta is 1 day, expect is 86400 + case 2: time delta is 1 day 3 hour 15 minutes 32 seconds, expect is 98132 + case 3: time delta is less than 1 day, only 1 hour 10 minutes, expect is 4200 + case 4: time delta is 1 hour ago, expect is -3600 + + Corner cases: + case 1: delta object is None -- invalid input, expect is + ''' + assert timeparser.timeDelta2secs(delta) == expect + + +def check_datetime_equal(d1, d2): + assert d1.year == d2.year + assert d1.month == d2.month + assert d1.day == d2.day + assert d1.hour == d2.hour + assert d1.minute == d2.minute + assert d1.second == d2.second + + +parse_time_math_params = [('+', '100', 's', datetime.datetime(2019, 3, 8, 4, 10, 20), + datetime.datetime(2019, 3, 8, 4, 12, 0)), + ('-', '20', 'm', datetime.datetime(2019, 3, 8, 4, 10, 20), + datetime.datetime(2017, 7, 8, 4, 10, 20)), + ('', '3', 'w', datetime.datetime(2019, 3, 8, 4, 10, 20), + datetime.datetime(2019, 3, 29, 4, 10, 20)), + ('', '0', 's', datetime.datetime(2019, 3, 8, 4, 10, 20), + datetime.datetime(2019, 3, 8, 4, 10, 20)), + ('', '123', '', datetime.datetime(2019, 3, 8, 4, 10, 20), + datetime.datetime(2019, 3, 8, 4, 10, 20))] + + +@pytest.mark.parametrize('plusminus,num,unit,ret,expect', parse_time_math_params) +def test_time_parser_time_math(plusminus, num, unit, ret, expect): + ''' + test timeParserTimeMath function, parse the time modifier + Normal Case: + Case 1: input "+100s" -- the parser should translate it as 100 seconds later. + Case 2: input "-20m" -- the parser should handle the month larger than 12 and translate as 20 months ago + Case 3: input '3w' -- the parser should translate as 21 days later. + + Corner Cases: + Case 1: input "0s" -- the time parser should return now + Case 2: input "123" -- unit is the empty string, behavior + ''' + check_datetime_equal(timeparser.timeParserTimeMath(plusminus, num, unichr, ret), expect) + + +def mock_now(): + return datetime.datetime(2019, 3, 10, 13, 20, 15) + + +def mock_utc_now(): + return datetime.datetime(2019, 3, 10, 5, 20, 15) + + +timeparser_params = [ + ('now', datetime.timedelta(days=1), datetime.datetime(2019, 3, 10, 13, 20, 15)), + ('now', datetime.timedelta(days=0), datetime.datetime(2019, 3, 10, 5, 20, 15)), + ('now', datetime.timedelta(hours=2), datetime.datetime(2019, 3, 10, 7, 20, 15)), + ('now', datetime.timedelta(hours=-3), datetime.datetime(2019, 3, 10, 2, 20, 15)), + ('-7d', datetime.timedelta(days=1), datetime.datetime(2019, 3, 3, 13, 20, 15)), + ('-0mon@mon', datetime.timedelta(days=1), datetime.datetime(2019, 3, 1, 0, 0, 0)), + ('-1mon@mon', datetime.timedelta(days=1), datetime.datetime(2019, 2, 1, 0, 0, 0)), + ('-3d@d', datetime.timedelta(days=1), datetime.datetime(2019, 3, 7, 0, 0, 0)), + ('+5d', datetime.timedelta(days=1), datetime.datetime(2019, 3, 15, 13, 20, 15)), + ('', datetime.timedelta(days=1), datetime.datetime(2019, 3, 10, 13, 20, 15)), ] + + +@pytest.mark.parametrize('ts,tz,expect', timeparser_params) +def test_timeparser(ts, tz, expect): + ''' + test timeParser function, parse splunk time modifier + Normal Cases: + Case 1: get now timestamp + Case 2: get utc now timestamp + Case 3: get utc+2 timezone timestamp + Case 4: get utc-2 timezone timestamp + Case 5: get the 7 days ago timestamp + Case 5: get the beginning of this month. check the snap to month + Case 6: get the beginning of last month. check the snap to last month + Case 7: get 3 days ago, snap to day + Case 8: get 5 days later + + Corner Cases: + Case 1: empty string as input. behavior + ''' + r = timeparser.timeParser(ts, tz, mock_now, mock_utc_now) + check_datetime_equal(r, expect)