keen-cli 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +77 -49
- data/keen-cli.gemspec +1 -1
- data/lib/keen-cli/batch_processor.rb +104 -0
- data/lib/keen-cli/cli.rb +9 -234
- data/lib/keen-cli/events.rb +70 -0
- data/lib/keen-cli/projects.rb +51 -0
- data/lib/keen-cli/queries.rb +138 -0
- data/lib/keen-cli/shared.rb +28 -0
- data/lib/keen-cli/utils.rb +18 -0
- data/lib/keen-cli/version.rb +1 -1
- data/lib/keen-cli.rb +16 -0
- data/spec/keen-cli/batch_processor_spec.rb +134 -0
- data/spec/keen-cli/cli_spec.rb +4 -161
- data/spec/keen-cli/events_spec.rb +41 -0
- data/spec/keen-cli/projects_spec.rb +42 -0
- data/spec/keen-cli/queries_spec.rb +106 -0
- data/spec/spec_helper.rb +13 -0
- metadata +17 -4
data/README.md
CHANGED
@@ -18,24 +18,25 @@ Verify the `keen` command is in your path by running it:
|
|
18
18
|
|
19
19
|
``` shell
|
20
20
|
Commands:
|
21
|
-
keen average
|
22
|
-
keen count
|
23
|
-
keen count-unique
|
24
|
-
keen events:add
|
25
|
-
keen extraction
|
26
|
-
keen help [COMMAND]
|
27
|
-
keen maximum
|
28
|
-
keen median
|
29
|
-
keen minimum
|
30
|
-
keen percentile
|
31
|
-
keen
|
32
|
-
keen
|
33
|
-
keen
|
34
|
-
keen
|
35
|
-
keen queries:run
|
36
|
-
keen
|
37
|
-
keen
|
38
|
-
keen
|
21
|
+
keen average # Alias for queries:run -a average
|
22
|
+
keen count # Alias for queries:run -a count
|
23
|
+
keen count-unique # Alias for queries:run -a count_unique
|
24
|
+
keen events:add # Add one or more events and print the result
|
25
|
+
keen extraction # Alias for queries:run -a extraction
|
26
|
+
keen help [COMMAND] # Describe available commands or one specific command
|
27
|
+
keen maximum # Alias for queries:run -a maximum
|
28
|
+
keen median # Alias for queries:run -a median
|
29
|
+
keen minimum # Alias for queries:run -a minimum
|
30
|
+
keen percentile # Alias for queries:run -a percentile
|
31
|
+
keen projects:collections # Print information about a project's collections
|
32
|
+
keen projects:describe # Print information about a project
|
33
|
+
keen projects:open # Open a project's overview page in a browser
|
34
|
+
keen projects:workbench # Open a project's workbench page in a browser
|
35
|
+
keen queries:run # Run a query and print the result
|
36
|
+
keen queries:url # Print the URL for a query
|
37
|
+
keen select-unique # Alias for queries:run -a select_unique
|
38
|
+
keen sum # Alias for queries:run -a sum
|
39
|
+
keen version # Print the keen-cli version
|
39
40
|
```
|
40
41
|
|
41
42
|
You should see information about available commands.
|
@@ -60,7 +61,7 @@ If you run `keen` from a directory with this .env file, it will assume the proje
|
|
60
61
|
To override the project context use the `--project` option:
|
61
62
|
|
62
63
|
``` shell
|
63
|
-
$ keen
|
64
|
+
$ keen projects:describe --project XXXXXXXXXXXXXXX
|
64
65
|
```
|
65
66
|
|
66
67
|
Similar overrides are available for specifiying API keys: `--master-key`, `--read-key` and `--write-key`.
|
@@ -68,13 +69,13 @@ Similar overrides are available for specifiying API keys: `--master-key`, `--rea
|
|
68
69
|
For example:
|
69
70
|
|
70
71
|
``` shell
|
71
|
-
$ keen
|
72
|
+
$ keen projects:describe --project XXXXXXXXXXXXXXX --master-key AAAAAAAAAAAAAA
|
72
73
|
```
|
73
74
|
|
74
75
|
Shorter aliases exist as well: `-p` for project, `-k` for master key, `-r` for read key, and `-w` for write key.
|
75
76
|
|
76
77
|
``` shell
|
77
|
-
$ keen
|
78
|
+
$ keen projects:describe -p XXXXXXXXXXXXXXX -k AAAAAAAAAAAAAA
|
78
79
|
```
|
79
80
|
|
80
81
|
### Usage
|
@@ -85,10 +86,10 @@ keen-cli has a variety of commands, and most are namespaced for clarity.
|
|
85
86
|
|
86
87
|
##### Projects
|
87
88
|
|
88
|
-
* `
|
89
|
-
* `
|
90
|
-
* `
|
91
|
-
* `
|
89
|
+
* `projects:open` - Open the Project Overview page in a browser
|
90
|
+
* `projects:workbench` - Open the Project Workbench page in a browser
|
91
|
+
* `projects:describe` - Get data about the project. Uses the [project row resource](https://keen.io/docs/api/reference/#project-row-resource).
|
92
|
+
* `projects:collections` - Get schema information about the project's collections. Uses the [event resource](https://keen.io/docs/api/reference/#event-resource).
|
92
93
|
|
93
94
|
##### Events
|
94
95
|
|
@@ -97,51 +98,58 @@ keen-cli has a variety of commands, and most are namespaced for clarity.
|
|
97
98
|
Parameters:
|
98
99
|
|
99
100
|
+ `--collection`, `-c`: The collection to add the event to. Alternately you can set `KEEN_COLLECTION_NAME` on the environment if you're working with the same collection frequently.
|
100
|
-
+ `--
|
101
|
-
|
102
|
-
|
101
|
+
+ `--batch-size`: Batch size of events posted to Keen, defaults to 1000.
|
102
|
+
|
103
|
+
Input source parameters:
|
104
|
+
|
105
|
+
+ `--data`, `-d`: Pass an event body on the command line. Make sure to use quotes where necessary.
|
106
|
+
+ `--file`, `-f`: The name of a file containing events.
|
107
|
+
|
108
|
+
You can also pass input via `STDIN`.
|
109
|
+
|
110
|
+
If not otherwise specified, the format of data from any source is assumed to be newline-delimited JSON. CSV and query string-like input is also supported. The associated params:
|
111
|
+
|
112
|
+
+ `--csv`: Specify CSV format. The first line must contain column names. Column names containing `.`, such as `keen.timestamp`, will be converted to nested properties.
|
113
|
+
+ `--params`: Specify "params" format. Params format looks like `property1=value1&property2=value` etc.
|
103
114
|
|
104
115
|
Various examples:
|
105
116
|
|
106
117
|
``` shell
|
107
|
-
#
|
118
|
+
# add an empty event
|
108
119
|
$ keen events:add --collection cli-tests
|
109
120
|
|
110
121
|
# use the shorter form of collection
|
111
122
|
$ keen events:add -c cli-tests
|
112
123
|
|
113
|
-
# add a blank event to a collection specified in
|
124
|
+
# add a blank event to a collection specified in a .env file:
|
114
125
|
# KEEN_COLLECTION_NAME=cli-tests
|
115
126
|
$ keen events:add
|
116
127
|
|
117
|
-
#
|
118
|
-
$ keen events:add -c cli-tests
|
128
|
+
# add an event from JSON using the --data parameter
|
129
|
+
$ keen events:add -c cli-tests --data "{ \"username\" : \"dzello\", \"zsh\": 1 }"
|
119
130
|
|
120
|
-
#
|
121
|
-
$ keen events:add -c cli-tests -
|
131
|
+
# add an event from key value pairs
|
132
|
+
$ keen events:add -c cli-tests -data "username=dzello&zsh=1" --params
|
122
133
|
|
123
134
|
# pipe in events as JSON
|
124
135
|
$ echo "{ \"username\" : \"dzello\", \"zsh\": 1 }" | keen events:add -c cli-tests
|
125
136
|
|
126
|
-
#
|
127
|
-
|
128
|
-
|
129
|
-
#
|
137
|
+
# add events from a file that contains newline delimited json
|
138
|
+
# { "apple" : "sauce" }
|
139
|
+
# { "banana" : "pudding" }
|
140
|
+
# { "cherry" : "pie" }
|
130
141
|
$ keen events:add --file events.json
|
131
142
|
|
132
|
-
#
|
133
|
-
|
134
|
-
|
135
|
-
#
|
136
|
-
|
137
|
-
# { "username" : "dkador", "zsh" : 1 }
|
138
|
-
# { "username" : "gphat", "zsh" : 1 }
|
139
|
-
$ cat events.json | keen events:add -c cli-test
|
143
|
+
# add events from a file in CSV format; the first row should be columns
|
144
|
+
# fruit,dish
|
145
|
+
# apple,sauce
|
146
|
+
# banana,pudding
|
147
|
+
$ keen events:add --file events.csv --csv
|
140
148
|
```
|
141
149
|
|
142
150
|
##### Queries
|
143
151
|
|
144
|
-
`queries:run` - Runs a query and prints the result
|
152
|
+
`queries:run` - Runs a query and prints the result
|
145
153
|
|
146
154
|
Parameters:
|
147
155
|
|
@@ -158,7 +166,11 @@ Parameters:
|
|
158
166
|
+ `--property-names`: A comma-separated list of property names. Extractions only.
|
159
167
|
+ `--latest`: Number of latest events to retrieve. Extractions only.
|
160
168
|
+ `--email`: Send extraction results via email, asynchronously. Extractions only.
|
161
|
-
|
169
|
+
|
170
|
+
Input source parameters:
|
171
|
+
+ `--data`, `-d`: Specify query parameters as JSON instead of query params.
|
172
|
+
|
173
|
+
You can also pass input via `STDIN`.
|
162
174
|
|
163
175
|
Some examples:
|
164
176
|
|
@@ -215,6 +227,16 @@ $ keen queries:run --collection minecraft-deaths --analysis-type extraction --pr
|
|
215
227
|
$ echo "{ \"event_collection\" : \"minecraft-deaths\", \"target_property\": \"level\" }" | keen queries:run -a average
|
216
228
|
```
|
217
229
|
|
230
|
+
**Query URL Generation**
|
231
|
+
|
232
|
+
Run `keen` with no arguments to see the full list of aliases.
|
233
|
+
|
234
|
+
`queries:url` - Generates the URL of a query, but does not run it.
|
235
|
+
|
236
|
+
The same parameters apply as `queries:run`, in addition to one extra.
|
237
|
+
|
238
|
+
+ `--exclude-api-key`: Prevent the API key query param from being included in the output
|
239
|
+
|
218
240
|
**Query Aliases**
|
219
241
|
|
220
242
|
For each type of analysis (e.g. count, average, extraction, etc.) there is an alias that can be used
|
@@ -228,10 +250,16 @@ $ keen minimum -c cpu-checks -y iowait
|
|
228
250
|
0.17
|
229
251
|
```
|
230
252
|
|
231
|
-
|
253
|
+
### Global parameters
|
254
|
+
|
255
|
+
Parameters that apply to most commands include:
|
256
|
+
|
257
|
+
+ `--pretty`: Prettify API response JSON. Defaults to true, set `--pretty=false` to prevent
|
258
|
+
+ `--silent`: Silence any output. Defaults to false.
|
232
259
|
|
233
260
|
### Changelog
|
234
261
|
|
262
|
+
+ 0.1.6 - Big refactoring to make importing events much cleaner and batching happen automatically. Also adds `queries:url`.
|
235
263
|
+ 0.1.5 – Support adding events from files with `--file`. Optionally add from CSV with `--csv`.
|
236
264
|
+ 0.1.4 – Support absolute timeframes via `--start` and `--end` flags
|
237
265
|
+ 0.1.3 – Add querying via JSON. Add query aliases. Add support for extraction fields.
|
data/keen-cli.gemspec
CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.description = "Record events and run queries from the comfort of your command line"
|
13
13
|
s.license = "MIT"
|
14
14
|
|
15
|
-
s.add_dependency "keen", ">= 0.8.
|
15
|
+
s.add_dependency "keen", ">= 0.8.6"
|
16
16
|
s.add_dependency "thor"
|
17
17
|
s.add_dependency "dotenv"
|
18
18
|
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module KeenCli
|
2
|
+
|
3
|
+
class BatchProcessor
|
4
|
+
|
5
|
+
# defaults
|
6
|
+
DEFAULT_BATCH_SIZE = 1000
|
7
|
+
DEFAULT_CSV_OPTIONS = { :converters => :all }
|
8
|
+
|
9
|
+
# public options, set in constructor
|
10
|
+
attr_accessor :collection
|
11
|
+
attr_accessor :batch_size
|
12
|
+
attr_accessor :params
|
13
|
+
attr_accessor :csv
|
14
|
+
attr_accessor :csv_options
|
15
|
+
attr_accessor :pretty
|
16
|
+
attr_accessor :silent
|
17
|
+
|
18
|
+
# internal state tracking
|
19
|
+
attr_accessor :size
|
20
|
+
attr_accessor :events
|
21
|
+
|
22
|
+
def initialize(collection, options={})
|
23
|
+
self.collection = collection
|
24
|
+
self.batch_size = options[:batch_size] || DEFAULT_BATCH_SIZE
|
25
|
+
self.csv = options[:csv]
|
26
|
+
self.params = options[:params]
|
27
|
+
self.csv_options = DEFAULT_CSV_OPTIONS.merge(options[:csv_options] || {})
|
28
|
+
self.events = []
|
29
|
+
self.pretty = options[:pretty]
|
30
|
+
self.silent = options[:silent]
|
31
|
+
self.reset
|
32
|
+
end
|
33
|
+
|
34
|
+
def add(line)
|
35
|
+
|
36
|
+
# if we're in CSV mode and don't have headers let's try and set them
|
37
|
+
if self.csv && !self.csv_options.has_key?(:headers)
|
38
|
+
|
39
|
+
set_headers(line)
|
40
|
+
return
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
if self.csv
|
45
|
+
|
46
|
+
csv_row = CSV.parse_line(line, self.csv_options)
|
47
|
+
raise "Could not parse! #{line}" unless csv_row
|
48
|
+
|
49
|
+
hash = row_to_hash(csv_row)
|
50
|
+
|
51
|
+
elsif self.params
|
52
|
+
|
53
|
+
hash = Utils.parse_data_as_querystring(line)
|
54
|
+
|
55
|
+
else
|
56
|
+
|
57
|
+
hash = JSON.parse(line)
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
self.events.push(hash)
|
62
|
+
self.size += 1
|
63
|
+
|
64
|
+
self.flush if self.size >= self.batch_size
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
def flush
|
69
|
+
publish_batch(self.collection, self.events) if self.size > 0
|
70
|
+
reset
|
71
|
+
end
|
72
|
+
|
73
|
+
def reset
|
74
|
+
self.size = 0
|
75
|
+
self.events.clear
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def set_headers(line)
|
81
|
+
csv_row = CSV.parse_line(line, self.csv_options)
|
82
|
+
self.csv_options[:headers] = csv_row.to_a
|
83
|
+
end
|
84
|
+
|
85
|
+
def publish_batch(collection, events)
|
86
|
+
batches = {}
|
87
|
+
batches[collection] = events
|
88
|
+
Keen.publish_batch(batches).tap do |result|
|
89
|
+
Utils.out_json(result, :pretty => self.pretty, :silent => self.silent)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def row_to_hash(csv_row)
|
94
|
+
naive_hash = csv_row.to_hash
|
95
|
+
naive_hash.map do |main_key, main_value|
|
96
|
+
main_key.to_s.split('.').reverse.inject(main_value) do |value, key|
|
97
|
+
{key => value}
|
98
|
+
end
|
99
|
+
end.inject(&:deep_merge)
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
data/lib/keen-cli/cli.rb
CHANGED
@@ -5,250 +5,25 @@ require 'csv'
|
|
5
5
|
|
6
6
|
require 'keen-cli/utils'
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
class CLI < Thor
|
11
|
-
|
12
|
-
def self.shared_options
|
13
|
-
option :project, :aliases => ['-p']
|
14
|
-
option :"master-key", :aliases => ['-k']
|
15
|
-
option :"read-key", :aliases => ['-r']
|
16
|
-
option :"write-key", :aliases => ['-w']
|
17
|
-
end
|
8
|
+
require 'keen-cli/shared'
|
18
9
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
def self.file_options
|
24
|
-
option :file, :aliases => ['-f']
|
25
|
-
option :csv
|
26
|
-
end
|
10
|
+
require 'keen-cli/projects'
|
11
|
+
require 'keen-cli/events'
|
12
|
+
require 'keen-cli/queries'
|
27
13
|
|
28
|
-
|
29
|
-
option :collection, :aliases => ['-c']
|
30
|
-
end
|
14
|
+
module KeenCli
|
31
15
|
|
32
|
-
|
33
|
-
self.collection_options
|
34
|
-
option :"analysis-type", :aliases => ['-a']
|
35
|
-
option :"group-by", :aliases => ['-g']
|
36
|
-
option :"target-property", :aliases => ['-y']
|
37
|
-
option :interval, :aliases => ['-i']
|
38
|
-
option :timeframe, :aliases => ['-t']
|
39
|
-
option :filters, :aliases => ['-f']
|
40
|
-
option :percentile
|
41
|
-
option :"property-names"
|
42
|
-
option :latest
|
43
|
-
option :email
|
44
|
-
option :start, :aliases => ['s']
|
45
|
-
option :end, :aliases => ['e']
|
46
|
-
end
|
16
|
+
class CLI < Thor
|
47
17
|
|
48
18
|
desc 'version', 'Print the keen-cli version'
|
49
19
|
map %w(-v --version) => :version
|
50
20
|
|
51
|
-
def version
|
52
|
-
"keen-cli version #{KeenCli::VERSION}".tap do |s|
|
53
|
-
puts s
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
desc 'project:describe', 'Print information about a project'
|
58
|
-
map 'project:describe' => :project_describe
|
59
|
-
shared_options
|
60
|
-
|
61
|
-
def project_describe
|
62
|
-
Utils.process_options!(options)
|
63
|
-
Keen.project_info.tap do |info|
|
64
|
-
puts JSON.pretty_generate(info)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
desc 'project:collections', 'Print information about a project\'s collections'
|
69
|
-
map 'project:collections' => :project_collections
|
70
|
-
shared_options
|
71
|
-
|
72
|
-
def project_collections
|
73
|
-
Utils.process_options!(options)
|
74
|
-
Keen.event_collections.tap do |collections|
|
75
|
-
puts JSON.pretty_generate(collections)
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
desc 'project:open', 'Open a project\'s overview page in a browser'
|
80
|
-
map 'project:open' => :project_open
|
81
|
-
shared_options
|
82
|
-
|
83
|
-
def project_open
|
84
|
-
Utils.process_options!(options)
|
85
|
-
"https://keen.io/project/#{Keen.project_id}".tap do |project_url|
|
86
|
-
`open #{project_url}`
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
desc 'project:workbench', 'Open a project\'s workbench page in a browser'
|
91
|
-
map 'project:workbench' => :project_workbench
|
92
|
-
shared_options
|
93
|
-
|
94
|
-
def project_workbench
|
95
|
-
Utils.process_options!(options)
|
96
|
-
"https://keen.io/project/#{Keen.project_id}/workbench".tap do |project_url|
|
97
|
-
`open #{project_url}`
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
desc 'queries:run', 'Run a query and print the result'
|
102
|
-
map 'queries:run' => :queries_run
|
103
21
|
shared_options
|
104
|
-
query_options
|
105
|
-
data_options
|
106
|
-
def queries_run(analysis_type=nil)
|
107
|
-
|
108
|
-
Utils.process_options!(options)
|
109
|
-
|
110
|
-
# work with a new set of options
|
111
|
-
q_options = {}
|
112
|
-
|
113
|
-
data = nil
|
114
|
-
|
115
|
-
if $stdin.tty?
|
116
|
-
data = options[:data]
|
117
|
-
else
|
118
|
-
ARGV.clear
|
119
|
-
ARGF.each_line do |line|
|
120
|
-
data = line
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
# if data is provided, parse it and merge it
|
125
|
-
unless data.nil?
|
126
|
-
data_options = JSON.parse(data)
|
127
|
-
q_options.merge!(data_options)
|
128
|
-
end
|
129
|
-
|
130
|
-
# convert dashes to underscores, and merge all into q_options
|
131
|
-
q_options.merge!(options.inject({}) do |memo, element|
|
132
|
-
if ['analysis-type', 'group-by', 'target-property', 'property-names'].include?(element.first)
|
133
|
-
memo[element.first.sub('-', '_')] = element.last
|
134
|
-
else
|
135
|
-
memo[element.first] = element.last
|
136
|
-
end
|
137
|
-
memo
|
138
|
-
end)
|
139
|
-
|
140
|
-
collection = Utils.get_collection_name(q_options)
|
141
|
-
analysis_type = analysis_type || q_options["analysis_type"]
|
142
|
-
|
143
|
-
# delete fields that shouldn't be passed to keen-gem as options
|
144
|
-
q_options.delete("collection")
|
145
|
-
q_options.delete("event_collection")
|
146
|
-
q_options.delete("data")
|
147
|
-
q_options.delete("analysis_type")
|
148
|
-
|
149
|
-
if property_names = q_options.delete("property_names")
|
150
|
-
q_options[:property_names] = property_names.split(",")
|
151
|
-
end
|
152
|
-
|
153
|
-
if start_time = q_options.delete("start")
|
154
|
-
q_options[:timeframe] = { :start => start_time }
|
155
|
-
end
|
156
|
-
|
157
|
-
if end_time = q_options.delete("end")
|
158
|
-
q_options[:timeframe] = q_options[:timeframe] || {}
|
159
|
-
q_options[:timeframe][:end] = end_time
|
160
|
-
end
|
161
|
-
|
162
|
-
raise "No analysis type given!" unless analysis_type
|
163
|
-
raise "No collection given!" unless collection
|
164
|
-
|
165
|
-
Keen.send(analysis_type, collection, q_options).tap do |result|
|
166
|
-
if result.is_a?(Hash) || result.is_a?(Array)
|
167
|
-
puts JSON.pretty_generate(result)
|
168
|
-
else
|
169
|
-
puts result
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
ANALYSIS_TYPES = %w(average count count-unique extraction median minimum maximum sum percentile select-unique)
|
175
|
-
|
176
|
-
ANALYSIS_TYPES.each do |analysis_type|
|
177
|
-
underscored_analysis_type = analysis_type.sub('-', '_')
|
178
|
-
desc analysis_type, "Alias for queries:run -c #{underscored_analysis_type}"
|
179
|
-
map analysis_type => method_name = "queries_run_#{underscored_analysis_type}"
|
180
|
-
shared_options
|
181
|
-
query_options
|
182
|
-
data_options
|
183
|
-
self.send(:define_method, method_name) { queries_run(underscored_analysis_type) }
|
184
|
-
end
|
185
|
-
|
186
|
-
desc 'events:add', 'Add one or more events and print the result'
|
187
|
-
map 'events:add' => :events_add
|
188
|
-
|
189
|
-
shared_options
|
190
|
-
data_options
|
191
|
-
file_options
|
192
|
-
collection_options
|
193
|
-
|
194
|
-
def events_add
|
195
|
-
|
196
|
-
events = []
|
197
|
-
collection = Utils.get_collection_name(options)
|
198
|
-
|
199
|
-
if options[:csv]
|
200
|
-
|
201
|
-
data = File.read(options[:file])
|
202
|
-
csv = CSV.new(data, :headers => true, :header_converters => :symbol, :converters => :all)
|
203
|
-
events = csv.to_a.map {|row| row.to_hash }
|
204
|
-
|
205
|
-
else
|
206
|
-
|
207
|
-
if $stdin.tty?
|
208
|
-
if data = options[:data]
|
209
|
-
events.push(data)
|
210
|
-
elsif file = options[:file]
|
211
|
-
File.readlines(file).each do |line|
|
212
|
-
events.push(line)
|
213
|
-
end
|
214
|
-
else
|
215
|
-
events.push({})
|
216
|
-
end
|
217
|
-
else
|
218
|
-
ARGV.clear
|
219
|
-
ARGF.each_line do |line|
|
220
|
-
events.push(line)
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
events = events.map do |event|
|
225
|
-
begin
|
226
|
-
JSON.parse(event)
|
227
|
-
rescue
|
228
|
-
begin
|
229
|
-
Utils.parse_data_as_querystring(event)
|
230
|
-
rescue
|
231
|
-
event
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
end
|
237
|
-
|
238
|
-
if events.length > 1
|
239
|
-
|
240
|
-
Keen.publish_batch(collection => events).tap do |result|
|
241
|
-
puts JSON.pretty_generate(result)
|
242
|
-
end
|
243
|
-
|
244
|
-
else
|
245
|
-
|
246
|
-
Keen.publish(collection, events.first).tap do |result|
|
247
|
-
puts JSON.pretty_generate(result)
|
248
|
-
end
|
249
22
|
|
23
|
+
def version
|
24
|
+
"keen-cli version #{KeenCli::VERSION}".tap do |s|
|
25
|
+
Utils.out(s, options)
|
250
26
|
end
|
251
|
-
|
252
27
|
end
|
253
28
|
|
254
29
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'keen-cli/batch_processor'
|
2
|
+
|
3
|
+
module KeenCli
|
4
|
+
|
5
|
+
class CLI < Thor
|
6
|
+
|
7
|
+
def self.events_options
|
8
|
+
option :csv
|
9
|
+
option :params
|
10
|
+
option :'batch-size'
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'events:add', 'Add one or more events and print the result'
|
14
|
+
map 'events:add' => :events_add
|
15
|
+
|
16
|
+
shared_options
|
17
|
+
data_options
|
18
|
+
file_options
|
19
|
+
collection_options
|
20
|
+
events_options
|
21
|
+
|
22
|
+
def events_add
|
23
|
+
|
24
|
+
Utils.process_options!(options)
|
25
|
+
|
26
|
+
collection = Utils.get_collection_name(options)
|
27
|
+
|
28
|
+
batch_processor = BatchProcessor.new(collection,
|
29
|
+
:csv => options[:csv],
|
30
|
+
:params => options[:params],
|
31
|
+
:pretty => options[:pretty],
|
32
|
+
:silent => options[:silent],
|
33
|
+
:batch_size => options[:'batch-size'])
|
34
|
+
|
35
|
+
total_events = 0
|
36
|
+
|
37
|
+
if data = options[:data]
|
38
|
+
batch_processor.add(data)
|
39
|
+
total_events += 1
|
40
|
+
end
|
41
|
+
|
42
|
+
if file = options[:file]
|
43
|
+
File.readlines(file).each do |line|
|
44
|
+
batch_processor.add(line)
|
45
|
+
total_events += 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
if !$stdin.tty?
|
50
|
+
ARGV.clear
|
51
|
+
ARGF.each_line do |line|
|
52
|
+
batch_processor.add(line)
|
53
|
+
total_events += 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if $stdin.tty? && data.nil? && file.nil?
|
58
|
+
batch_processor.add("{}")
|
59
|
+
total_events += 1
|
60
|
+
end
|
61
|
+
|
62
|
+
batch_processor.flush
|
63
|
+
|
64
|
+
total_events
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|