@@ -25,87 +25,128 @@ import (
25
25
)
26
26
27
27
var (
28
- exitOnError = flag .Bool (
28
+ globalFlags = flag .NewFlagSet ("global config flags" , flag .ExitOnError )
29
+
30
+ exitOnError = globalFlags .Bool (
29
31
"exit-on-error" ,
30
32
true ,
31
33
"Exit with a message when there's an error" ,
32
34
)
33
- verbose = flag .Bool (
35
+ verbose = globalFlags .Bool (
34
36
"verbose" ,
35
37
false ,
36
38
"Write logs to terminal" ,
37
39
)
38
- fakeAvgAggregates = flag .Bool (
40
+ fakeAvgAggregates = globalFlags .Bool (
39
41
"fake-avg-aggregates" ,
40
42
true ,
41
43
"Generate sum/cnt series out of avg series to accommodate metrictank" ,
42
44
)
43
- httpEndpoint = flag .String (
45
+ httpEndpoint = globalFlags .String (
44
46
"http-endpoint" ,
45
47
"127.0.0.1:8080" ,
46
48
"The http endpoint to listen on" ,
47
49
)
48
- cassandraAddrs = flag .String (
49
- "cassandra-addrs" ,
50
- "localhost" ,
51
- "cassandra host (may be given multiple times as comma-separated list)" ,
52
- )
53
- cassandraKeyspace = flag .String (
54
- "cassandra-keyspace" ,
55
- "metrictank" ,
56
- "cassandra keyspace to use for storing the metric data table" ,
57
- )
58
- ttlsStr = flag .String (
50
+ ttlsStr = globalFlags .String (
59
51
"ttls" ,
60
52
"35d" ,
61
53
"list of ttl strings used by MT separated by ','" ,
62
54
)
63
- windowFactor = flag .Int (
55
+ windowFactor = globalFlags .Int (
64
56
"window-factor" ,
65
57
20 ,
66
58
"the window factor be used when creating the metric table schema" ,
67
59
)
68
- partitionScheme = flag .String (
60
+ partitionScheme = globalFlags .String (
69
61
"partition-scheme" ,
70
62
"bySeries" ,
71
63
"method used for partitioning metrics. This should match the settings of tsdb-gw. (byOrg|bySeries)" ,
72
64
)
73
- uriPath = flag .String (
65
+ uriPath = globalFlags .String (
74
66
"uri-path" ,
75
67
"/chunks" ,
76
68
"the URI on which we expect chunks to get posted" ,
77
69
)
78
- numPartitions = flag .Int (
70
+ numPartitions = globalFlags .Int (
79
71
"num-partitions" ,
80
72
1 ,
81
73
"Number of Partitions" ,
82
74
)
75
+
76
+ cassandraAddrs = globalFlags .String ("cassandra-addrs" , "localhost" , "cassandra host (may be given multiple times as comma-separated list)" )
77
+ cassandraKeyspace = globalFlags .String ("cassandra-keyspace" , "raintank" , "cassandra keyspace to use for storing the metric data table" )
78
+ cassandraConsistency = globalFlags .String ("cassandra-consistency" , "one" , "write consistency (any|one|two|three|quorum|all|local_quorum|each_quorum|local_one" )
79
+ cassandraHostSelectionPolicy = globalFlags .String ("cassandra-host-selection-policy" , "tokenaware,hostpool-epsilon-greedy" , "" )
80
+ cassandraTimeout = globalFlags .Int ("cassandra-timeout" , 1000 , "cassandra timeout in milliseconds" )
81
+ cassandraReadConcurrency = globalFlags .Int ("cassandra-read-concurrency" , 20 , "max number of concurrent reads to cassandra." )
82
+ cassandraReadQueueSize = globalFlags .Int ("cassandra-read-queue-size" , 100 , "max number of outstanding reads before blocking. value doesn't matter much" )
83
+ cassandraRetries = globalFlags .Int ("cassandra-retries" , 0 , "how many times to retry a query before failing it" )
84
+ cqlProtocolVersion = globalFlags .Int ("cql-protocol-version" , 4 , "cql protocol version to use" )
85
+
86
+ cassandraSSL = globalFlags .Bool ("cassandra-ssl" , false , "enable SSL connection to cassandra" )
87
+ cassandraCaPath = globalFlags .String ("cassandra-ca-path" , "/etc/metrictank/ca.pem" , "cassandra CA certificate path when using SSL" )
88
+ cassandraHostVerification = globalFlags .Bool ("cassandra-host-verification" , true , "host (hostname and server cert) verification when using SSL" )
89
+
90
+ cassandraAuth = globalFlags .Bool ("cassandra-auth" , false , "enable cassandra authentication" )
91
+ cassandraUsername = globalFlags .String ("cassandra-username" , "cassandra" , "username for authentication" )
92
+ cassandraPassword = globalFlags .String ("cassandra-password" , "cassandra" , "password for authentication" )
93
+
83
94
GitHash = "(none)"
84
95
printLock sync.Mutex
85
96
)
86
97
87
98
type Server struct {
88
- Cluster * gocql.ClusterConfig
89
99
Session * gocql.Session
90
100
TTLTables mdata.TTLTables
91
101
Partitioner partitioner.Partitioner
92
102
Index idx.MetricIndex
93
103
}
94
104
95
105
func main () {
96
- cassandra .ConfigSetup ()
97
- flag .Parse ()
106
+ cassFlags := cassandra .ConfigSetup ()
107
+
108
+ flag .Usage = func () {
109
+ fmt .Println ("mt-whisper-importer-writer" )
110
+ fmt .Println ()
111
+ fmt .Println ("Opens an endpoint to send data to, which then gets stored in the MT internal DB(s)" )
112
+ fmt .Println ()
113
+ fmt .Printf ("Usage:\n \n " )
114
+ fmt .Printf (" mt-whisper-importer-writer [global config flags] <idxtype> [idx config flags] \n \n " )
115
+ fmt .Printf ("global config flags:\n \n " )
116
+ globalFlags .PrintDefaults ()
117
+ fmt .Println ()
118
+ fmt .Printf ("idxtype: only 'cass' supported for now\n \n " )
119
+ fmt .Printf ("cass config flags:\n \n " )
120
+ cassFlags .PrintDefaults ()
121
+ fmt .Println ()
122
+ fmt .Println ("EXAMPLES:" )
123
+ fmt .Println ("mt-whisper-importer-writer -cassandra-addrs=192.168.0.1 -cassandra-keyspace=mydata -exit-on-error=true -fake-avg-aggregates=true -http-endpoint=0.0.0.0:8080 -num-partitions=8 -partition-scheme=bySeries -ttls=8d,2y -uri-path=/chunks -verbose=true -window-factor=20 cass -hosts=192.168.0.1:9042 -keyspace=mydata" )
124
+ }
98
125
99
- cassCluster := gocql .NewCluster (strings .Split (* cassandraAddrs , "," )... )
100
- cassCluster .Consistency = gocql .ParseConsistency ("one" )
101
- cassCluster .Timeout = time .Second
102
- cassCluster .NumConns = 2
103
- cassCluster .ProtoVersion = 4
104
- cassCluster .Keyspace = * cassandraKeyspace
126
+ if len (os .Args ) == 2 && (os .Args [1 ] == "-h" || os .Args [1 ] == "--help" ) {
127
+ flag .Usage ()
128
+ os .Exit (0 )
129
+ }
130
+
131
+ var cassI int
132
+ for i , v := range os .Args {
133
+ if v == "cass" {
134
+ cassI = i
135
+ }
136
+ }
137
+ if cassI == 0 {
138
+ fmt .Println ("only indextype 'cass' supported" )
139
+ flag .Usage ()
140
+ os .Exit (1 )
141
+ }
142
+
143
+ globalFlags .Parse (os .Args [1 :cassI ])
144
+ cassFlags .Parse (os .Args [cassI + 1 : len (os .Args )])
145
+ cassandra .Enabled = true
105
146
106
- session , err := cassCluster . CreateSession ( )
147
+ store , err := mdata . NewCassandraStore ( * cassandraAddrs , * cassandraKeyspace , * cassandraConsistency , * cassandraCaPath , * cassandraUsername , * cassandraPassword , * cassandraHostSelectionPolicy , * cassandraTimeout , * cassandraReadConcurrency , * cassandraReadConcurrency , * cassandraReadQueueSize , 0 , * cassandraRetries , * cqlProtocolVersion , * windowFactor , * cassandraSSL , * cassandraAuth , * cassandraHostVerification , nil )
107
148
if err != nil {
108
- panic (fmt .Sprintf ("Failed to create cassandra session : %q" , err ))
149
+ panic (fmt .Sprintf ("Failed to initialize cassandra: %q" , err ))
109
150
}
110
151
111
152
splits := strings .Split (* ttlsStr , "," )
@@ -121,8 +162,7 @@ func main() {
121
162
}
122
163
123
164
server := & Server {
124
- Cluster : cassCluster ,
125
- Session : session ,
165
+ Session : store .Session ,
126
166
TTLTables : ttlTables ,
127
167
Partitioner : p ,
128
168
Index : cassandra .New (),
@@ -131,6 +171,7 @@ func main() {
131
171
server .Index .Init ()
132
172
133
173
http .HandleFunc (* uriPath , server .chunksHandler )
174
+ http .HandleFunc ("/healthz" , server .healthzHandler )
134
175
135
176
log (fmt .Sprintf ("Listening on %q" , * httpEndpoint ))
136
177
err = http .ListenAndServe (* httpEndpoint , nil )
@@ -158,6 +199,10 @@ func log(msg string) {
158
199
}
159
200
}
160
201
202
+ func (s * Server ) healthzHandler (w http.ResponseWriter , req * http.Request ) {
203
+ w .Write ([]byte ("ok" ))
204
+ }
205
+
161
206
func (s * Server ) chunksHandler (w http.ResponseWriter , req * http.Request ) {
162
207
metric := & archive.Metric {}
163
208
err := metric .UnmarshalCompressed (req .Body )
0 commit comments