vayacondios-server 0.2.11 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/.gitignore +3 -1
  2. data/.travis.yml +2 -0
  3. data/Gemfile +15 -9
  4. data/LICENSE.md +2 -6
  5. data/Procfile +1 -1
  6. data/README.md +656 -111
  7. data/Rakefile +89 -6
  8. data/bin/vcd +10 -0
  9. data/bin/vcd-server +8 -0
  10. data/config/database.yml +6 -0
  11. data/config/spec.example.yml +18 -0
  12. data/config/vayacondios.example.yml +15 -0
  13. data/config/vcd-server.rb +37 -0
  14. data/examples/configuration.rb +56 -0
  15. data/examples/event_stream.rb +19 -0
  16. data/examples/simple.rb +61 -0
  17. data/features/event.feature +319 -0
  18. data/features/events.feature +208 -0
  19. data/features/stash.feature +840 -0
  20. data/features/stashes.feature +492 -0
  21. data/features/step_definitions/stash_steps.rb +113 -0
  22. data/features/stream.feature +30 -0
  23. data/features/support/em.rb +14 -0
  24. data/features/support/env.rb +13 -0
  25. data/lib/vayacondios/configuration.rb +63 -0
  26. data/lib/vayacondios/server/api.rb +126 -0
  27. data/lib/vayacondios/server/api_options.rb +56 -0
  28. data/lib/vayacondios/server/configuration.rb +23 -0
  29. data/lib/vayacondios/server/driver.rb +71 -0
  30. data/lib/vayacondios/server/drivers/mongo.rb +126 -0
  31. data/lib/vayacondios/server/handlers/document_handler.rb +81 -0
  32. data/lib/vayacondios/server/handlers/event_handler.rb +31 -26
  33. data/lib/vayacondios/server/handlers/events_handler.rb +31 -0
  34. data/lib/vayacondios/server/handlers/stash_handler.rb +69 -0
  35. data/lib/vayacondios/server/handlers/stashes_handler.rb +49 -0
  36. data/lib/vayacondios/server/handlers/stream_handler.rb +39 -0
  37. data/lib/vayacondios/server/models/document.rb +87 -0
  38. data/lib/vayacondios/server/models/event.rb +198 -0
  39. data/lib/vayacondios/server/models/stash.rb +100 -0
  40. data/lib/vayacondios/server.rb +35 -0
  41. data/lib/vayacondios-server.rb +19 -13
  42. data/lib/vayacondios.rb +22 -0
  43. data/pom.xml +124 -4
  44. data/spec/configuration_spec.rb +41 -0
  45. data/spec/server/api_options_spec.rb +32 -0
  46. data/spec/server/api_spec.rb +279 -0
  47. data/spec/server/configuration_spec.rb +27 -0
  48. data/spec/server/drivers/mongo_spec.rb +107 -0
  49. data/spec/server/handlers/event_handler_spec.rb +62 -0
  50. data/spec/server/handlers/events_handler_spec.rb +51 -0
  51. data/spec/server/handlers/stash_handler_spec.rb +68 -0
  52. data/spec/server/handlers/stashes_handler_spec.rb +50 -0
  53. data/spec/server/handlers/stream_handler_spec.rb +5 -0
  54. data/spec/server/models/document_spec.rb +9 -0
  55. data/spec/server/models/event_spec.rb +185 -0
  56. data/spec/server/models/stash_spec.rb +95 -0
  57. data/spec/spec_helper.rb +23 -3
  58. data/spec/support/database_helper.rb +42 -0
  59. data/spec/support/log_helper.rb +19 -0
  60. data/spec/support/shared_context_for_events.rb +22 -0
  61. data/spec/support/shared_context_for_stashes.rb +24 -0
  62. data/spec/support/shared_examples_for_handlers.rb +32 -0
  63. data/src/main/java/com/infochimps/vayacondios/BaseClient.java +342 -0
  64. data/src/main/java/com/infochimps/vayacondios/HTTPClient.java +426 -0
  65. data/src/main/java/com/infochimps/vayacondios/VayacondiosClient.java +487 -65
  66. data/src/main/java/com/infochimps/vayacondios/test/IntegrationTest.java +3 -0
  67. data/src/test/java/com/infochimps/vayacondios/BaseClientTest.java +50 -0
  68. data/src/test/java/com/infochimps/vayacondios/HTTPClientIT.java +267 -0
  69. data/vayacondios-server.gemspec +9 -9
  70. metadata +127 -122
  71. checksums.yaml +0 -15
  72. data/.rspec +0 -2
  73. data/.yardopts +0 -10
  74. data/Guardfile +0 -41
  75. data/app/http_shim.rb +0 -71
  76. data/bin/vcd.sh +0 -27
  77. data/config/http_shim.rb +0 -43
  78. data/config/vayacondios.example.yaml +0 -7
  79. data/config/vayacondios.yaml +0 -7
  80. data/examples/java/ItemSetTest.java +0 -76
  81. data/lib/tasks/publish.rake +0 -23
  82. data/lib/tasks/spec.rake +0 -11
  83. data/lib/tasks/yard.rake +0 -2
  84. data/lib/vayacondios/client/config.rb +0 -7
  85. data/lib/vayacondios/client/configliere.rb +0 -38
  86. data/lib/vayacondios/client/cube_client.rb +0 -39
  87. data/lib/vayacondios/client/http_client.rb +0 -49
  88. data/lib/vayacondios/client/itemset.rb +0 -130
  89. data/lib/vayacondios/client/legacy_switch.rb +0 -43
  90. data/lib/vayacondios/client/notifier.rb +0 -123
  91. data/lib/vayacondios/client/zabbix_client.rb +0 -148
  92. data/lib/vayacondios/legacy_switch.rb +0 -43
  93. data/lib/vayacondios/server/errors/bad_request.rb +0 -6
  94. data/lib/vayacondios/server/errors/not_found.rb +0 -6
  95. data/lib/vayacondios/server/handlers/config_handler.rb +0 -32
  96. data/lib/vayacondios/server/handlers/itemset_handler.rb +0 -60
  97. data/lib/vayacondios/server/legacy_switch.rb +0 -43
  98. data/lib/vayacondios/server/model/config_document.rb +0 -89
  99. data/lib/vayacondios/server/model/document.rb +0 -25
  100. data/lib/vayacondios/server/model/event_document.rb +0 -94
  101. data/lib/vayacondios/server/model/itemset_document.rb +0 -126
  102. data/lib/vayacondios/server/rack/extract_methods.rb +0 -35
  103. data/lib/vayacondios/server/rack/jsonize.rb +0 -43
  104. data/lib/vayacondios/server/rack/params.rb +0 -50
  105. data/lib/vayacondios/server/rack/path.rb +0 -23
  106. data/lib/vayacondios/server/rack/path_validation.rb +0 -22
  107. data/lib/vayacondios/version.rb +0 -3
  108. data/lib/vayacondios-client.rb +0 -22
  109. data/scripts/hadoop_monitor/configurable.rb +0 -66
  110. data/scripts/hadoop_monitor/hadoop_attempt_scraper.rb +0 -45
  111. data/scripts/hadoop_monitor/hadoop_client.rb +0 -273
  112. data/scripts/hadoop_monitor/hadoop_monitor.rb +0 -101
  113. data/scripts/hadoop_monitor/hadoopable.rb +0 -65
  114. data/scripts/hadoop_monitor/machine_monitor.rb +0 -115
  115. data/scripts/s3_cataloger/buckets +0 -33
  116. data/scripts/s3_cataloger/foreach_bucket +0 -88
  117. data/scripts/s3_cataloger/parse_ls.py +0 -391
  118. data/spec/client/itemset_legacy_spec.rb +0 -55
  119. data/spec/client/itemset_spec.rb +0 -60
  120. data/spec/client/notifier_spec.rb +0 -120
  121. data/spec/server/config_spec.rb +0 -113
  122. data/spec/server/event_spec.rb +0 -103
  123. data/spec/server/itemset_legacy_spec.rb +0 -320
  124. data/spec/server/itemset_spec.rb +0 -317
  125. data/spec/server/rack/extract_methods_spec.rb +0 -60
  126. data/spec/server/rack/path_spec.rb +0 -36
  127. data/spec/server/rack/path_validation_spec.rb +0 -22
  128. data/spec/server/server_spec.rb +0 -20
  129. data/spec/support/mongo_cleaner.rb +0 -32
  130. data/src/main/java/ItemSetTest.java +0 -76
  131. data/src/main/java/com/infochimps/util/CurrentClass.java +0 -26
  132. data/src/main/java/com/infochimps/util/DebugUtil.java +0 -38
  133. data/src/main/java/com/infochimps/util/HttpHelper.java +0 -181
  134. data/src/main/java/com/infochimps/vayacondios/ItemSets.java +0 -373
  135. data/src/main/java/com/infochimps/vayacondios/LinkToVCD.java +0 -18
  136. data/src/main/java/com/infochimps/vayacondios/MemoryVCDShim.java +0 -84
  137. data/src/main/java/com/infochimps/vayacondios/Organization.java +0 -62
  138. data/src/main/java/com/infochimps/vayacondios/PathBuilder.java +0 -13
  139. data/src/main/java/com/infochimps/vayacondios/StandardVCDLink.java +0 -218
  140. data/src/main/java/com/infochimps/vayacondios/VCDIntegrationTest.java +0 -108
  141. data/src/test/java/com/infochimps/vayacondios/TestVayacondiosInMemory.java +0 -78
  142. data/vayacondios-client.gemspec +0 -25
data/README.md CHANGED
@@ -1,189 +1,734 @@
1
- # Vaya con Dios
1
+ # Vayacondios
2
2
 
3
- ## Warning
3
+ Vayacondios is a server-client program designed to make it simple to
4
+ collect and centralize information and metrics from a large number of
5
+ disparate sources from multiple application domains.
4
6
 
5
- Some of the documentation on this page is for legacy versions of
6
- Vayacondios. Until this document is updated, please see the specs for
7
- the Ruby code or compile the javadocs for the Java API.
7
+ Vayacondios has the following design goals:
8
8
 
9
- > "Data goes in. The right thing happens."
9
+ The client is simple enough to use in a shell script and the server is
10
+ performant enough to support ubiquitous use across a large
11
+ installation with many clients.
10
12
 
11
- Simple enough to use in a shell script, performant enough to use everywhere.
13
+ * *Decentralized* -- Any client can dispatch stashes or events from anywhere
14
+ * *Dynamic* -- No data types or schemas need to be created in advance
15
+ * *Ubiquitous* -- Clients require minimal dependencies because the API is simple to use and access
16
+ * *Simple* -- Clients can write data in whatever way is natural for them
17
+ * *Scalable* -- Server and storage can be scaled horizontally to allow for ever-increasing loads
18
+ * *Fast* -- No client should have to worry that sending data to Vayacondios will affect its performance
12
19
 
13
- You can chuck the following into Vaya con Dios from Ruby, the shell, over HTTP, or in a repeated polling loop:
20
+ The basic objects of Vayacondios are **stash** and the **event**:
14
21
 
15
- * *value* -- 'there are 3 cups of coffee remaining':
16
- * *timing* -- 'this response took 100ms'
17
- * *count* -- 'I just served a 404 response code'
18
- * *fact* -- 'here's everything to know about the coffee machine: `{"cups_remaining":3,"uptime":127,room:"hyrule"}`' -- an arbitrary JSON hash
22
+ * a **stash** is an "object", a "configuration", or "setting" designed to be shared among many services
23
+ * an **event** is a "fact", "measurement", or "metric" announced by an arbitrary service, possibly related to some stash
19
24
 
20
- ### Design goals
25
+ Stashes and events are each documents which can contain arbitrary
26
+ JSON-serializable data: hashes/maps/dictionarys, arrays/lists,
27
+ strings, numbers, floats, null, &c.
21
28
 
22
- * *Decentralized* -- Any (authorized) system can dispatch facts or metrics using an arbitrary namespace and schema. Nothing needs to be created in advance.
23
- * *Bulletproof* -- UDP clients will never fail because of network loss or timeout.
24
- * *Fast* -- UDP clients are non-blocking and happily dispatch thousands of requests per second.
25
- * *Minimal Dependency* -- Ruby clients uses nothing outside of the standard libraries.
26
- * *Ubiquitous* -- Can send facts from the shell (with nothing besides `curl`)
27
- * *writes are simple, reads are clever* -- A writer gets to chuck things in according to its conception of the world.
29
+ The client and server communicate over a RESTful, HTTP-based API which
30
+ speaks JSON.
28
31
 
29
32
  See also [Coda Hale's metrics](https://github.com/codahale/metrics/).
30
33
 
31
- ## Namespacing
34
+ <a name="architecture" />
35
+ ## Architecture
32
36
 
33
- The first path segment defines a collection, and the remainder defines a [materialized path](http://www.mongodb.org/display/DOCS/Trees+in+MongoDB#TreesinMongoDB-MaterializedPaths%28FullPathinEachNode%29).
34
- All hashes within a given path should always have the same structure. Writes to an overlapping key will overwrite.
37
+ <a name="architecture-database" />
38
+ ### Database
35
39
 
36
- A full Vaya con Dios path is broken down into specific segments.
40
+ Vayacondios stores all its data in a database. Access to the database
41
+ within Vayacondios is strictly contained within model classes within
42
+ `lib/vayacondios/server/models`. This is so that the backend database
43
+ can one day be changed easily without affecting the rest of the
44
+ application.
37
45
 
38
- `/:organization/(event|config)/:topic.format`
46
+ [MongoDB](http://www.mongodb.org/) is currently the only supported
47
+ database. MongoDB is a natural choice because it exposes atomic query
48
+ primitives which map very closely to the operations exposed by the
49
+ Vayacondios API.
39
50
 
40
- * `:organization` is the top level collection that all info is contained in.
41
- * `(event|config)` changes the context of the message. Events are timestamped and scope destructive. Config is merged with the current configuration.
42
- * `topic` is the materialized path we referred to that specifies its unique location.
43
- * `format` will change the serialization format for the data. Only JSON is currently supported.
51
+ <a name="architecture-server" />
52
+ ### Server
44
53
 
54
+ The Vayacondios server process is a
55
+ [Goliath](https://github.com/postrank-labs/goliath) web server which
56
+ implements the Vayacondios API over HTTP using JSON.
57
+
58
+ A single server process can easily handle hundreds of client requests
59
+ per second. Multiple Vayacondios servers can easily be deployed
60
+ behind a load-balancer.
61
+
62
+ Each running server process reads and writes all its data in a single
63
+ MongoDB database specified at runtime.
64
+
65
+ <a name="architecture-client" />
66
+ ### Client
67
+
68
+ Clients communicate with the Vayacondios server via the HTTP API it
69
+ exposes. This makes it extremely simply for applications in any
70
+ language to communicate with the server.
71
+
72
+ Vayacondios comes with several clients:
73
+
74
+ * a Ruby-language client (`Vayacondios::HttpClient`)
75
+ * a Java-language client (`com.infochimps.vayacondios.HTTPClient`)
76
+ * a command-line client (the `vcd` program)
77
+
78
+ The Ruby-language client and the command-line client are bundled with
79
+ the `vayacondios-client` Ruby gem. The Java-language client is part
80
+ of the `com.infochimps.vayacondios` package.
81
+
82
+ <a name="datamodel" />
83
+ ## Data Model
84
+
85
+ Vayacondios uses a two-level hierarchical data model to organize
86
+ events and stashes.
87
+
88
+ The top-level is the **organization**. Data from multiple
89
+ organizations is stored together but accessed separately by a running
90
+ Vayacondios server. An organization could be the name of a user,
91
+ workgroup, application, or service using Vayacondios.
92
+
93
+ The next level is the **topic**. Each topic within Vayacondios has a
94
+ single stash and can have multiple events. An "object" like a server,
95
+ a database, an application, a service, or a user maps to the concept
96
+ of "topic".
97
+
98
+ Topics and organizations are strings which can only contain letters,
99
+ digits, underscores, periods, and hypens, though periods cannot be the
100
+ first or last character. Organizations cannot begin with the string
101
+ `system.`.
102
+
103
+ <a name="datamodel-events" />
45
104
  ### Events
46
105
 
47
- Events are the primary piece of information stored. An event is anything that happened that you'd want to write down.
106
+ Events belong to a topic within an organization. Each event
107
+ additionally has
108
+
109
+ * an ID which is automatically set by the server to a random, unique value if none is provided when the event is announced. Provided IDs cannot contain periods or dollar signs.
110
+ * a timestamp which is automatically set by the server to the current UTC time if none is provided when the event is announced. Provided timestamps will attempt to be parsed either from a string or from an integer UNIX timestamp.
111
+ * arbitrary key/value data. Keys cannot contain periods or dollar signs.
112
+
113
+ Events are used for storing facts, measurements, metrics, errors,
114
+ occurrences, &c. If you anticipate wanting to see a time series or a
115
+ histogram of a certain kind of data then you should consider writing
116
+ that data into Vayacondios as events on some topic.
117
+
118
+ Events are stored in MongoDB in a collection named after their
119
+ organization and topic: an event on the `ci` topic for the `example`
120
+ organization would be stored in the MongoDB collection
121
+ `example.ci.events`. The ID of the event, whether auto-generated by
122
+ the server or specified by the client, will be used as the `_id` field
123
+ of the resulting document within this collection.
48
124
 
125
+ Here are some examples of data that it would make sense to store as
126
+ events (in JSON format):
49
127
 
50
- For example a `POST` to `http://vayacondios.whatever.com/v1/code/commit` with the
128
+ * the output of a build from a CI system might be written to topic `ci`
51
129
  ```
52
130
  {
53
- "_id": "f93f2f08a0e39648fe64", # commit SHA as unique id
54
- "_path": "code.commit", # materialized path
55
- "_ts": "20110614104817", # utc flat time
56
- "repo": "infochimps/wukong"
57
- "message": "...",
58
- "lines": 69,
59
- "author": "mrflip"
131
+ "environment": "Jenkins CI v. 1.519",
132
+ "project": {
133
+ "name": "website",
134
+ "version": "0b4d99ded50a19e495d2472477bbb0784d8a18d8",
135
+ "url": "https://github.com/mycompany/website.git",
136
+ },
137
+ "build": {
138
+ "time": 182,
139
+ "status": "success"
140
+ },
141
+ "test": {
142
+ "time": 97,
143
+ "ran": 102,
144
+ "passed": 102,
145
+ "failed": 0
146
+ }
147
+ }
148
+ ```
149
+ * an intrusion event picked up by the firewall might be written to topic `firewall.intrusions`
150
+ ```
151
+ {
152
+ "ip": "74.210.29.117",
153
+ "port": 22,
154
+ "type": "ssh",
155
+ "reason": "blacklisted"
60
156
  }
61
157
  ```
158
+ * some performance statistics for a running server might be written topic `phoenix.servers.webserver-16`
159
+ ```
160
+ {
161
+ "data_center": "Phoenix",
162
+ "rack": "14",
163
+ "server": "webserver-16",
164
+ "cpu": {
165
+ user: 3.17,
166
+ nice: 0.01,
167
+ system: 0.27,
168
+ iowait: 0.18,
169
+ steal: 0.00,
170
+ idle: 96.38
171
+ },
172
+ "mem": {
173
+ "total": 12304632,
174
+ "used": 10335900,
175
+ "free": 1968732
176
+ },
177
+ "net": {
178
+ "out": 2.25,
179
+ "in": 10.28,
180
+ },
181
+ "disk": {
182
+ "write": 16.182,
183
+ "read": 0.11
184
+ }
185
+ ```
186
+
187
+ <a name="datamodel-stashes" />
188
+ ### Stashes
189
+
190
+ Stashes belong to a topic within an organization. Each stash
191
+ additionally has arbitrary key/value data that it can store. Keys
192
+ cannot contain dollar signs or periods.
193
+
194
+ Stashes are used for storing objects, configuration, settings, &c. If
195
+ you anticipate wanting to lookup a value by name then you should
196
+ consider writing that data into Vayacondios as (or within) a stash on
197
+ some topic.
198
+
199
+ The names of top-level keys within a stash can be used as the "ID"
200
+ when retrieving/setting/deleting values via the API.
201
+
202
+ Stashes are stored in MongoDB in a collection named after their
203
+ organization: a stash for the `example` organization would be stored
204
+ in the MongoDB collection `example.stash`. The topic of the stash
205
+ will be used as the `_id` field of the resulting document within this
206
+ collection.
207
+
208
+ Here are some examples of data that it would make sense to store as
209
+ stashes (in JSON format):
210
+
211
+ * a collection of projects to run through a CI system might be stored on topic `ci`
212
+ ```
213
+ {
214
+ "projects": {
215
+ {
216
+ "name": "website",
217
+ "url": "https://github.com/mycompany/website.git",
218
+ },
219
+ {
220
+ "name": "client_tool",
221
+ "url": "https://github.com/mycompany/client_tool.git",
222
+ },
223
+ ...
224
+ }
225
+ }
226
+ ```
227
+ * firewall settings might be stored on topic `firewall`
228
+ ```
229
+ {
230
+ "firewall": {
231
+ "rules": [
232
+ {
233
+ "range": "0.0.0.0",
234
+ "port": 80,
235
+ "protocol": "tcp"
236
+ },
237
+ {
238
+ "range": "10.0.0.0",
239
+ "port"; 22,
240
+ "protocol": "ssh"
241
+ }
242
+ ]
243
+ }
244
+ }
245
+ ```
246
+ * a mapping of servers within some data center might be stored on topic `data_centers.phoenix`
247
+ ```
248
+ {
249
+ "name": "PHX",
250
+ "location": "Phoenix, AZ",
251
+ "servers": [
252
+ "webserver-0",
253
+ "webserver-1",
254
+ "webserver-2",
255
+ ...
256
+ ]
257
+ }
258
+ ```
259
+
260
+ <a name="installation" />
261
+ ## Installation & Configuration
262
+
263
+ <a name="installation-database" />
264
+ ### Database
265
+
266
+ Vayacondios server depends on a database to store all its data.
267
+ Currently, only MongoDB is supported: here are some
268
+ [installation instructions](http://docs.mongodb.org/manual/installation/).
269
+
270
+ <a name="installation-server" />
271
+ ### Server
272
+
273
+ Vayacondios server is distributed via Rubygems:
274
+
275
+ ```
276
+ $ sudo gem install vayacondios-server
277
+ ```
278
+
279
+ Once installed, you can launch a copy of the server from the
280
+ command-line running locally on port 9000:
281
+ ```
282
+ $ vcd-server --verbose --stdout
283
+ ```
284
+
285
+ Ports, logging, the location of MongoDB, and much more can be
286
+ configured via command-line options. Try `vcd-server --help` for more
287
+ details.
288
+
289
+ <a name="installation-client" />
290
+ ### Client
291
+
292
+ The server exposes its API via HTTP so all sorts of clients can talk
293
+ to Vayacondios server. Most simply, a command like
294
+
295
+ ```
296
+ $ curl -X POST http://localhost:9000/v2/my_organization/event/some_topic -d '{"event": "data"}'
297
+ ```
298
+
299
+ will work "right out of the box".
300
+
301
+ You can also install some pre-written clients that are aware of the
302
+ Vayacondios API.
303
+
304
+ <a name="installation-client-cli" />
305
+ #### Command-Line
306
+
307
+ The `vcd` command-line client is installed via Rubygems:
308
+
309
+ ```
310
+ $ sudo gem install vayacondios-client
311
+ ```
312
+
313
+ You can now run the `vcd` program. The equivalent to the above `curl`
314
+ command would be
315
+
316
+ ```
317
+ $ vcd announce 'some_topic' '{"event": "data"}'
318
+ ```
319
+
320
+ The `vcd` program looks for its configuration (where is the
321
+ Vayacondios server? what organization am I in?) in the files
322
+ `/etc/vayacondios/vayacondios.yml` and `~/.vayacondios.yml`. The
323
+ following can be put in either location to customize the behavior of
324
+ `vcd` for a given server or user.
325
+
326
+ ```yml
327
+ ---
328
+ host: vcd.example.com
329
+ port: 9000
330
+ organization: my_company
331
+ ```
332
+
333
+ <a name="installation-client-ruby" />
334
+ #### Ruby Client
335
+
336
+ A Ruby client is also avialable via Rubygems:
337
+
338
+ ```
339
+ $ sudo gem install vayacondios-client
340
+ ```
341
+
342
+ You can now use the `Vayacondios::HttpClient` class in your code:
343
+
344
+ ```ruby
345
+ require 'vayacondios-client'
346
+ client = Vayacondios::HttpClient.new(organization: 'my_company')
347
+ client.announce('some_topic', foo: 'bar')
348
+ ```
349
+
350
+ The Ruby client exposes several API requests as named methods (like
351
+ `announce` above, which maps to a <a
352
+ href="#api-events-announce">announce event</a> API endpoint).
353
+
354
+ <a name="installation-client-java" />
355
+ #### Java Client
356
+
357
+ A Java client is also available. Put the following into your
358
+ `pom.xml`:
359
+
360
+ ```xml
361
+ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
362
+ ...
363
+ <repositories>
364
+ ...
365
+ <repository>
366
+ <id>infochimps.releases</id>
367
+ <name>Infochimps Internal Repository</name>
368
+ <url>https://s3.amazonaws.com/artifacts.chimpy.us/maven-s3p/releases</url>
369
+ </repository>
370
+ ...
371
+ </repositories>
372
+ ...
373
+ <dependencies>
374
+ ...
375
+ <dependency>
376
+ <groupId>com.infochimps</groupId>
377
+ <artifactId>vayacondios</artifactId>
378
+ <version>2.0.0</version>
379
+ </dependency>
380
+ ...
381
+ </dependencies>
382
+ ...
383
+ </project>
384
+ ```
385
+
386
+ You can now use the `com.infochimps.vayacondios.HTTPClient` class in
387
+ your code:
388
+
389
+ ```java
390
+ import com.infochimps.vayacondios.VayacondiosClient;
391
+ import com.infochimps.vayacondios.HTTPClient;
392
+
393
+ class public HelloVayacondios {
394
+ public static void main(String[] args) throws Exception {
395
+ VayacondiosClient client = new HTTPClient("my_organization");
396
+ Map event = new HashMap();
397
+ event.put("foo", "bar");
398
+ client.announce("my_topic", event);
399
+ Thread.sleep(50) // ensures async HTTP request finishes
400
+ client.close();
401
+ }
402
+ }
403
+ ```
404
+
405
+ The Java client exposes several API requests as named methods (like
406
+ `announce` above, which maps to a <a
407
+ href="#api-events-announce">announce event</a> API endpoint).
408
+
409
+ <a name="api" />
410
+ ## API (v2)
411
+
412
+ All HTTP endpoints defined by the Vayacondios server API share a
413
+ common structure: `/:version/:organization/:type/[:topic]/[:id]/...`
414
+
415
+ | Parameter | Required | Definition | Examples |
416
+ | ------------ | -------- | ------------------------------------- | ------------------------------------- |
417
+ | version | required | Vayacondios API version | v1, v2 (current) |
418
+ | organization | required | Name of organization, service, or app | `security`, `accounting`, `customerX` |
419
+ | type | required | Request type | `event`, `stash`, `events`, `stashes` |
420
+ | topic | varies | Topic for event or stash | `firewall`, `servers.webserver-3` |
421
+ | id | varies | ID of event or field within stash | `cpu`, `liua38923u2389f` |
422
+
423
+ The `version`, `organization`, and `type` parameters are always
424
+ required. Other parameters are required depending on the endpoint.
425
+
426
+ Vayacondios server only listens for a single value of the top-level
427
+ `version` parameter (curently: `v2`). A frontend webserver (Apache,
428
+ nginx, &c.) can be used to split traffic to backend Vayacondios
429
+ servers running different versions of the Vayacondios API by routing
430
+ based on this parameter.
431
+
432
+ The `type` parameter is fixed and defines the type of a Vayacondios
433
+ request: `event`, `stash`, `events`, or `stashes`.
434
+
435
+ All other parameters are completely free for clients to specify under
436
+ the following constraints:
437
+
438
+ * the `organization` parameter can only contain letters, digits,
439
+ hyphens, and underscores and it must begin with a letter
440
+
441
+ * the `topic` parameter can only contain letters, digits, hyphens,
442
+ underscores, and periods and it cannot start or end with a period
443
+
444
+ * the `id` parameter cannot contain the dollar sign or period
445
+
446
+ The `type`, `organization`, `topic`, and `id` parameter together
447
+ constitue the *vayacondios route*.
448
+
449
+ The *document* is the request body sent to the server with a given
450
+ request. Requests to Vayacondios should have JSON-encoded bodies but
451
+ the body can be any JSON datatype: Hash, Array, String, Integer,
452
+ Float, Boolean, or `null`.
453
+
454
+ The *response* is the JSON-encoded response body sent back to the
455
+ client from the server. If an error occurred, in addition to the
456
+ appropriate HTTP response code, the response will be a Hash containing
457
+ the key `error` with a message detailing the error.
458
+
459
+ In the case of a record which is not found, the response may be empty
460
+ but the HTTP response code will be 404.
461
+
462
+ In the case of a successful request, the response code will be 200 and
463
+ the response body will the requested/written object.
464
+
465
+ <a name="api-events" />
466
+ ### Events
467
+
468
+ A topic within an organization can have many events.
469
+
470
+ Events are Hash-like data structures which have an associated
471
+ timestamp and ID.
472
+
473
+ Events can be announced, retrieved, and searched. Events cannot be
474
+ updated or deleted, though announcing an event with the same ID as an
475
+ existing event overwrites the existing event.
476
+
477
+ <a name="api-events-announce" />
478
+ #### Announce a new event
479
+
480
+ An event can be created without an ID. The server will generate a
481
+ random, unique ID and include it with the event in the response. This
482
+ is the most common way to write an event. If you don't intend to ever
483
+ retrieve this specific event (as opposed to searching across events)
484
+ then this is the right choice.
485
+
486
+ Events can also be created with an explicit ID. This is less common
487
+ but can be useful if your events naturally contain a unique
488
+ identifier.
489
+
490
+ | Method | Path | Request | Response | Action |
491
+ | ------ | ---------------------------------- | ------- | -------- | ----------------------------------------------- |
492
+ | POST | /v2/:organization/event/:topic | Hash | Hash | Stores a new event with an auto-generated ID |
493
+ | POST | /v2/:organization/event/:topic/:id | Hash | Hash | Stores/overwrites a new event with the given ID |
494
+
495
+ All requests to announce a new event accept a Hash-like request body.
496
+ Key/value pairs in this request body constitute the body of the event.
497
+ The following parameters have special meaning:
498
+
499
+ | Parameter | Description | Default | Example Values |
500
+ | --------- | ------------------------------ | ------------ | ---------------------------------------- |
501
+ | time | Set the timestamp of the event | current time |`2013-06-20 16:20:48 -0500`, `1371763237` |
502
+
503
+ The response body will contain a Hash that is the original request
504
+ Hash but with the (possibly auto-generated) ID and timestamp included.
505
+
506
+ <a name="api-events-get" />
507
+ #### Get an existing event
508
+
509
+ Events can be retrieved if their ID is known.
510
+
511
+ | Method | Path | Request | Response | Action |
512
+ | ------ | ---------------------------------- | ------- | -------- | ----------------------------------------------- |
513
+ | GET | /v2/:organization/event/:topic/:id | N/A | Hash | Retrieve an existing event given its ID |
514
+
515
+ The response will contain the event Hash if found or will be empty if
516
+ not.
517
+
518
+ <a name="api-events-search" />
519
+ #### Search for events
520
+
521
+ You can search for events matching a query.
522
+
523
+ | Method | Path | Request | Response | Action |
524
+ | ------ | ------------------------------- | ------- | ----------- | ----------------------------------------------- |
525
+ | GET | /v2/:organization/events/:topic | Hash | Array<Hash> | Search for events on the given topic. |
526
+
527
+ The default behavior (which will occur with an empty request body) is
528
+ to return the most recent 50 events on the given `topic` sorted in
529
+ descending order by their timestamps.
530
+
531
+ Each key in the query body will be interpeted as a condition that the
532
+ data of each event must match in order to be returned. Keys with
533
+ periods are interpreted as nested fields. The following parameters
534
+ have special meaning and can be used to adjust the time window, number
535
+ of returned events, the sort behavior, and the fields within each
536
+ event to return:
62
537
 
63
- Will write the hash as shown into the `code` collection. Vaya con Dios fills in the _path always, and the _id and _ts if missing. This can be queried with path of "^commit/infochimps" or "^commit/.*".
538
+ | Parameter | Description | Default | Example Values |
539
+ | --------- | -------------------------------------------- | -------------------- | ------------------------------------------------------ |
540
+ | from | Occurred after this time | 1 hour ago | `2013-06-20 Thu 00:00:00 -0500`, 1371704400 |
541
+ | upto | Occurred before this time | current time | `2013-06-20 Thu 23:59:59 -0500`, 1371790799 |
542
+ | limit | Return up to this many events | 50 | 100, 200 |
543
+ | fields | Return only these fields from the event body | all fields | `["account_id", "ip_address"]` |
544
+ | sort | Sort returned events by this field | descending by time | `["time", "ascending"]`, `["ip_address", "ascending"]` |
545
+ | id | Regular expression search on event ID | N/A | `sensor-data-.*`, `2013-06-20-.*` |
64
546
 
65
- The hash will contain:
547
+ The response will be an Array of the matching events, possibly an
548
+ empty Array if no events were found.
66
549
 
67
- * `_id` -- unique _id
68
- * `_ts` -- timestamp, set if blank
69
- * `_path` -- `name.spaced.path.fact_name`, omits the collection part
550
+ <a name="api-stashes" />
551
+ ### Stashes
70
552
 
553
+ A topic within an organization can have a stash.
71
554
 
72
- ### Writes
555
+ Stashes are Hash-like data structures. Each key/value pair with the
556
+ stash can be accessed directly by using the name of its key as the ID
557
+ in requests.
73
558
 
74
- * value
75
- * count
76
- * timing
77
- * fact
559
+ Stashes can be set, merged, retrieved, searched, and destroyed.
78
560
 
79
- `echo 'bob.dobolina.mr.bob.dobolina:320|ms:320' | netcat -c -u 127.0.0.1 8125`
561
+ <a name="api-stashes-set" />
562
+ #### Set a value
80
563
 
81
- `http://vayacondios:9000/bob/dobolina/mr/bob/dobolina?_count=1`
564
+ You can set a value for a stash or one of the fields within a stash.
565
+ Your value will override whatever value is currently stored for that
566
+ stash or for that ID within the stash.
82
567
 
83
- `http://vayacondios:9000/bob/dobolina/mr/bob/dobolina?_count=1&_sampling=0.1`
568
+ | Method | Path | Request | Response | Action |
569
+ | ------ | ---------------------------------- | ------- | -------- | ---------------------------------------------------------- |
570
+ | POST | /v2/:organization/stash/:topic | Hash | Hash | Overwrites the stash with the given topic. |
571
+ | POST | /v2/:organization/stash/:topic/:id | varies | varies | Overwrites the ID field of the stash with the given topic. |
84
572
 
85
- `http://vayacondios:9000/bob/dobolina/mr/bob/dobolina?_timing=320`
573
+ When setting the stash itself, your value must be Hash-like. When
574
+ setting an ID within a stash, your value can have any datatype.
86
575
 
87
- ### also
576
+ The response for setting a stash will be the (Hash-like) stash you
577
+ just set. When setting an ID within a stash, the response will be of
578
+ the same datatype as the request.
88
579
 
89
- * Path components must be ASCII strings matching `[a-z][a-z0-9_]+` -- that is, start with [a-z] and contain only lowercase alphanumeric or underscore. Components starting with a '_' have reserved meanings. The only valid underscored fields that a request can fill in are _id, _ts and _path.
580
+ #### Merge a value
90
581
 
91
- * Vaya con Dios reserves the right to read and write paths in `/vayacondios`, and the details of those paths will be documented; it will never read or write other paths unless explicitly asked to.
582
+ You can merge a value for a stash or one of the fields within a stash.
92
583
 
93
- * tree_merge rules:
584
+ | Method | Path | Request | Response | Action |
585
+ | ------ | ---------------------------------- | ------- | -------- | ----------------------------------------------------------- |
586
+ | PUT | /v2/:organization/stash/:topic | Hash | Hash | Merges into the stash with the given topic. |
587
+ | PUT | /v2/:organization/stash/:topic/:id | varies | varies | Merges into the ID field of the stash with the given topic. |
94
588
 
95
- - hash1 + hash = hash1.merge(hash)
96
- - arr1 + arr2 = arr1 + arr2
97
- - val1 + val2 = val2
589
+ When merging the stash itself, your value must be Hash-like and will
590
+ be merged on top of the existing (Hash-like) stash's value.
98
591
 
99
- - hsh1 + nil = hsh1
100
- - arr1 + nil = arr1
101
- - val1 + nil = val1
592
+ When merging one of the ID fields within the stash, your value can
593
+ have any datatype and it will be intelligently merged:
102
594
 
103
- - nil + hs## = hsh2
104
- - nil + arr2 = arr2
105
- - nil + val2 = val2
595
+ * if your value is Hash-like and the existing value is Hash-like , your new value will be merged on top of the existing value
596
+ * if your value is Array-like and the existing value is Array-like , your new value will be concatenated to the end of the existing value
597
+ * if your value is String-like and the existing value is String-like , your new value will be concatenated to the end of the existing value
598
+ * if your value is Numeric-like and the existing value is Numeric-like , your new value will be added to the existing value
106
599
 
107
- - otherwise, exception
600
+ The response for merging a stash will be the Hash-like combination of
601
+ your old and new value. The response for merging an ID within a stash
602
+ will be of the same type as the request.
108
603
 
109
- types: Hash, Array, String, Time, Integer, Float, Nil
604
+ <a name="api-stashes-get" />
605
+ #### Get a value
110
606
 
111
- mongo: string, int, double, boolean, date, bytearray, object, array, others
112
- couch: string,number,boolean,array,object
607
+ You can get the value of an existing stash or one of the fields within
608
+ that stash.
113
609
 
114
- #### add (set? send?)
610
+ | Method | Path | Request | Response | Action |
611
+ | ------ | ---------------------------------- | ------- | -------- | ------------------------------------------------------ |
612
+ | GET | /v2/:organization/stash/:topic | N/A | Hash | Return the stash with the given topic. |
613
+ | GET | /v2/:organization/stash/:topic/:id | N/A | varies | Return the ID field of the stash with the given topic. |
115
614
 
116
- GET http://vayacondios:9099/f/{clxn}/{arbitrary/name/space}.{ext}?auth=token&query=predicate
615
+ The response for retreiving a stash will be the Hash-like stash while
616
+ the response for retreving an ID field within a stash will vary based
617
+ on the datatype of that value.
117
618
 
118
- db.collection(collection).save
619
+ <a name="api-stashes-delete" />
620
+ #### Delete a value
119
621
 
622
+ You can get delete a stash or one of the fields within a stash.
120
623
 
121
- get
624
+ | Method | Path | Request | Response | Action |
625
+ | ------ | ---------------------------------- | ------- | -------- | ------------------------------------------------------- |
626
+ | DELETE | /v2/:organization/stash/:topic | N/A | Hash | Deletes the stash with the given topic. |
627
+ | DELETE | /v2/:organization/stash/:topic/:id | N/A | Hash | Deletes the ID field of the stash with the given topic. |
122
628
 
629
+ The response for deleting a stash or an ID within a stash will be a
630
+ Hash naming the topic (and ID if given in the request) deleted.
123
631
 
124
- #### get
632
+ <a name="api-stashes-search" />
633
+ #### Search for stashes
125
634
 
126
- POST http://vayacondios:9099/f/arbitrary/name/space with JSON body
635
+ You can search for stashes.
127
636
 
128
- #### Increment
637
+ | Method | Path | Request | Response | Action |
638
+ | ------ | --------------------------- | ------- | -------- | ------------------------------------------------------- |
639
+ | GET | /v2/:organization/stashes | Hash | Array<Hash> | Search for stashes matching the given query. |
129
640
 
130
- #### Add to set
641
+ The default behavior (which will occur with an empty request body) is
642
+ to return 50 stashes in sorted in ascending order by their topic.
131
643
 
132
- what do we need to provide the 'I got next' feature (to distribute resources uniquely from a set)?
644
+ Each key in the query body will be interpreted as a condition that the
645
+ data of each stash must match in order to be returned. Keys with
646
+ periods are interpreted as nested fields. The following parameters
647
+ have special meaning and can be used to adjust the number of returned
648
+ stashes, the fields within each stash, and the the sort behavior.
133
649
 
134
- #### Auth
650
+ | Parameter | Description | Default | Example Values |
651
+ | ------------- | ---------------------------------------------- | -------------------- | ---------------------------------- |
652
+ | limit | Return up to this many stashes | 50 | 100, 200 |
653
+ | sort | Sort returned stashes by this field | ascending by topic | `["ip_address", "ascending"]` |
654
+ | fields | Array of fields to include in the response | all fields | `["name", "address", "phone"]` |
655
+ | topic | Regular expression search on the stash's topic | N/A | `servers-.*`, `firewall\..*\.rule` |
656
+ | topic_in | List of explicit topics to match | N/A | `["servers.bob", "servers.alan"]` |
657
+ | topic_not_in | List of explicit topics to **not** match | N/A | `["servers.bob", "servers.alan"]` |
135
658
 
136
- `/vayacondios/_auth/` holds one hash giving public key.
137
- * walk down the hash until you see _tok
138
- * can only auth at first or second level?
139
- * or by wildcard?
140
- * access is read or read_write; by default allows read_write
659
+ The response will be an Array of the matching stashes, possibly an
660
+ empty Array if no events were found.
141
661
 
142
- ## Others
662
+ #### Update Multiple Stashes
143
663
 
144
- GET latest
145
- GET all
146
- GET next
664
+ There are two related methods that let you update multiple stashes in
665
+ place according to the same rule.
147
666
 
148
- ## Configuration
667
+ | Method | Path | Request | Response | Action |
668
+ | ------ | ------------------------- | ------- | -------- | --------------------------------------------------- |
669
+ | PUT | /v2/:organization/stashes | Hash | Hash | Apply an update to all stashes matching a query |
670
+ | POST | /v2/:organization/stashes | Hash | Hash | Apply a replacement to all stashes matching a query |
149
671
 
150
- All organizations have a special topic called, "config" that allows for storage and retrieval of configuration data via standard [CRUD requests](http://en.wikipedia.org/wiki/Create,_read,_update_and_delete).
672
+ Each of these methods accepts a Hash request body that is supposed to have the following parameters:
151
673
 
152
- ### Writing config data
674
+ | Parameter | Description | Default | Example Values |
675
+ | --------- | -------------------------------------------------- | ------- | ----------------------------------------------- |
676
+ | query | A Hash of matching criteria the stash must satisfy | N/A | `{"region": "dakota"}` |
677
+ | update | An update to apply to each matched stash | N/A | `{"status": "disabled", "service.ftp": "down"}` |
153
678
 
154
- A `POST` request can be made to a full URL such as: `http://vayacondios:9000/organization/topic/some/deep/key`
679
+ The methods differ in the way they process the `update`. The `POST`
680
+ method will always replace the existing values of the named fields
681
+ (top-level or nested) in the update Hash with their new, updated
682
+ values. This is useful when you want to explicitly set a property to
683
+ some fixed value for all stashes which match some criteria.
155
684
 
156
- Vaya con Dios stores configuration data in special collections (`"#{organization}.config"`). The topic acts as the primary key while `/some/deep/key` acts as a materialized path for selection.
685
+ The `PUT` method (like the `PUT /v2/:organization/stash/:topic`
686
+ method) tries to be more clever and attempts to *merge* the update
687
+ into the record according to the following rules
157
688
 
158
- ## Notes
689
+ * if your value is Numeric-like, your new value will be added to the existing value
690
+ * if your value is Array-like, your new value will be concatenated to the end of the existing value
691
+ * if your value is Hash-like, it will replace the existing value (**Note::** this is different than the behavior of `PUT /v2:organization/stash/:stopic`.)
692
+ * if your value is String-like, it will replace the existing value (**Note::** this is different than the behavior of `PUT /v2:organization/stash/:stopic`.)
159
693
 
160
- ### When to use HTTP vs UDP
694
+ Notice that the behavior for Hashes and Strings isn't as nice as it is
695
+ for `PUT /v2:organization/stash/:stopic`. Still, this method is
696
+ useful for when you want to increment some value across all stashes
697
+ which match some criteria.
161
698
 
162
- #### HTTP is connectionful
699
+ For both of these methods, the query Hash also contains parameters
700
+ that are very similar to when searching for a stash:
163
701
 
164
- * you get acknowledgement that a metric was recorded (this is good).
165
- * if the network is down, your code will break (this is bad). (Well, usually. For some accounting and auditing metrics one might rather serve nothing at all than something unrecorded. Vayacondios doesn't address this use case.)
702
+ | Parameter | Description | Default | Example Values |
703
+ | ------------- | ---------------------------------------------- | -------------------- | ---------------------------------- |
704
+ | topic | Regular expression search on the stash's topic | N/A | `servers-.*`, `firewall\..*\.rule` |
705
+ | topic_in | List of explicit topics to match | N/A | `["servers.bob", "servers.alan"]` |
706
+ | topic_not_in | List of explicit topics to **not** match | N/A | `["servers.bob", "servers.alan"]` |
166
707
 
167
- #### UDP has Packet Size limitations
708
+ Other fields in the query Hash are interpreted as requirements on the
709
+ data in the stash itself.
168
710
 
169
- If you're using UDP for facts, you need to be *very* careful about payload size.
711
+ #### Deleting Multiple Stashes
170
712
 
171
- From the [EventMachine docs](http://eventmachine.rubyforge.org/EventMachine/Connection.html#M000298)
713
+ The following method can be used to delete multiple stashes which all
714
+ match some criteria:
172
715
 
173
- > You may not send an arbitrarily-large data packet because your operating system will enforce a platform-specific limit on the size of the outbound packet. (Your kernel will respond in a platform-specific way if you send an overlarge packet: some will send a truncated packet, some will complain, and some will silently drop your request). On LANs, it’s usually OK to send datagrams up to about 4000 bytes in length, but to be really safe, send messages smaller than the Ethernet-packet size (typically about 1400 bytes). Some very restrictive WANs will either drop or truncate packets larger than about 500 bytes.
716
+ | Method | Path | Request | Response | Action |
717
+ | ------ | ------------------------- | ------- | -------- | ----------------------------------- |
718
+ | DELETE | /v2/:organization/stashes | Hash | Hash | Delete all stashes matching a query |
174
719
 
175
- ## Colophon
720
+ The following request parameters define the query which is used to
721
+ match stashes to be deleted:
176
722
 
177
- ### Contributing to vayacondios
723
+ | Parameter | Description | Default | Example Values |
724
+ | ------------- | ---------------------------------------------- | -------------------- | ---------------------------------- |
725
+ | topic | Regular expression search on the stash's topic | N/A | `servers-.*`, `firewall\..*\.rule` |
726
+ | topic_in | List of explicit topics to match | N/A | `["servers.bob", "servers.alan"]` |
727
+ | topic_not_in | List of explicit topics to **not** match | N/A | `["servers.bob", "servers.alan"]` |
178
728
 
179
- * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
180
- * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
181
- * Fork the project
182
- * Start a feature/bugfix branch
183
- * Commit and push until you are happy with your contribution
184
- * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
185
- * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
729
+ Other fields in the query Hash are interpreted as requirements on the
730
+ data in the stash itself in order for it to match and be deleted.
186
731
 
187
732
  ### Copyright
188
733
 
189
- Copyright (c) 2011, 2012 Infochimps. See [LICENSE.md](LICENSE.md) for further details.
734
+ Copyright (c) 2011 - 2013 Infochimps. See [LICENSE.md](LICENSE.md) for further details.