Skip to content

Commit 53d3746

Browse files
authored
Merge pull request #177 from v3io/development
Development --> Master (0.0.13)
2 parents 4e4c9b9 + 3159dfb commit 53d3746

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1225
-1063
lines changed

Diff for: .travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ go:
66
script:
77
- make test
88
- make lint
9+
- V3IO_TSDB_CONFIG="$TRAVIS_BUILD_DIR/travis_v3io.yaml" TSDB_TEST_TABLE_PATH="TSDB_INTEGRATION_TESTS/$TRAVIS_BUILD_NUMBER" make integration
910

1011
before_deploy:
1112
- GOOS=linux GOARCH=amd64 make build

Diff for: README.md

+21-19
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ The code is separated to Prometheus compliant adapter in [/promtsdb](promtsdb) a
6969
[v3iotsdb_test.go](/pkg/tsdb/v3iotsdb_test.go), both have similar semantics.
7070

7171
For Prometheus you would need to use the fork found in `https://github.com/v3io/prometheus`, it already loads this
72-
library, you would need to place a `v3io.yaml` file with relevant configuration in the same folder as the Prometheus
72+
library, you would need to place a `v3io-tsdb-config.yaml` file with relevant configuration in the same folder as the Prometheus
7373
executable (see details on configurations below).
7474

7575
A developer using this library should first create a TSDB, this can be done using the CLI or an API call (`CreateTSDB`)
@@ -102,20 +102,20 @@ For use with nuclio function you can see function example under [\nuclio](exampl
102102
### Creating and Configuring a TSDB Adapter
103103

104104
The first step is to create a TSDB, this is done only once per TSDB and generates the required metadata and configuration
105-
such as partitioning strategy, retention, aggregators, etc. this can be done via the CLI or a function call.
105+
such as partitioning strategy, retention, aggregates, etc. this can be done via the CLI or a function call.
106106

107107
```go
108108
// Load v3io connection/path details (see YAML below)
109-
v3iocfg, err := config.GetOrLoadFromFile("v3io.yaml")
109+
v3iocfg, err := config.GetOrLoadFromFile("v3io-tsdb-config.yaml")
110110
if err != nil {
111111
// TODO: handle error
112112
}
113113

114114
// Specify the default DB configuration (can be modified per partition)
115-
sampleRate = "1/s"
116-
aggregatorGranularity = "1h"
115+
samplesIngestionRate = "1/s"
116+
aggregationGranularity = "1h"
117117
aggregatesList = "scount,avg,min,max"
118-
schema, err := schema.NewSchema(v3iocfg, sampleRate, aggregatorGranularity, aggregatesList)
118+
schema, err := schema.NewSchema(v3iocfg, samplesIngestionRate, aggregationGranularity, aggregatesList)
119119
if err != nil {
120120
// TODO: handle error
121121
}
@@ -132,22 +132,24 @@ parameters: the configuration structure, v3io data container object and logger o
132132
you already have container and logger (when using nuclio data bindings).
133133

134134
Configuration is specified in a YAML or JSON format, and can be read from a file using `config.GetOrLoadFromFile(path string)`
135-
or can be loaded from a local buffer using `config.GetOrLoadFromData(data []byte)`. You can see details on the configuration
136-
options in [config](internal/pkg/config/config.go), a minimal configuration looks like:
135+
or can be loaded from a local buffer using `config.GetOrLoadFromData(data []byte)`.
136+
You can see details on the configuration options in the V3IO TSDB [**config.go**](pkg/config/config.go) source file.
137+
A template configuration file is found at **examples/v3io-tsdb-config.yaml.template**.
138+
You can use it as a reference for creating your own TSDB configuration file.
139+
For example:
137140

138141
```yaml
139-
v3ioUrl: "v3io address:port"
142+
webApiEndpoint: "192.168.1.100:8081"
140143
container: "tsdb"
141-
path: performance
142-
username: "<username>"
143-
password: "<password>"
144+
username: "johnd"
145+
password: "OpenSesame"
144146
```
145147
146-
example of creating an adapter:
148+
Following is an example of code for creating an adapter:
147149
148150
```go
149151
// create configuration object from file
150-
cfg, err := config.GetOrLoadFromFile("v3io.yaml")
152+
cfg, err := config.GetOrLoadFromFile("v3io-tsdb-config.yaml")
151153
if err != nil {
152154
// TODO: handle error
153155
}
@@ -175,8 +177,8 @@ Example:
175177

176178
// create metrics labels, `__name__` label specify the metric type (e.g. cpu, temperature, ..)
177179
// the other labels can be used in searches (filtering or grouping) or aggregations
178-
// use utils.FromStrings(s ...string) for string list input or utils.FromMap(m map[string]string) for map input
179-
lset := utils.FromStrings("__name__","http_req", "method", "post")
180+
// use utils.LabelsFromStrings(s ...string) for string list input or utils.LabelsFromMap(m map[string]string) for map input
181+
lset := utils.LabelsFromStrings("__name__","http_req", "method", "post")
180182

181183
// Add a sample with current time (in milisec) and the value of 7.9
182184
ref, err := appender.Add(lset, time.Now().Unix * 1000, 7.9)
@@ -197,8 +199,8 @@ The `Querier` interface is used to query the database and return one or more met
197199
and specify the query window (min and max times), once we did we can use `Select()` or `SelectOverlap()` commands which will
198200
return a list of series (as an iterator object).
199201

200-
Every returned series have two interfaces, `Labels()` which returns the series or aggregator labels, and `Iterator()`
201-
which returns an iterator over the series or aggregator values.
202+
Every returned series have two interfaces, `Labels()` which returns the series or aggregate labels, and `Iterator()`
203+
which returns an iterator over the series or aggregate values.
202204

203205
The `Select()` call accepts 4 parameters:
204206
* name (string) - optional, metric type (e.g. cpu, memory, ..), specifying it accelerate performance (use range queries)
@@ -208,7 +210,7 @@ The `Select()` call accepts 4 parameters:
208210

209211
using `functions` and `step` is optional, use it only when you are interested in pre-aggregation and the step is >> than
210212
the sampling interval (and preferably equal or greater than the partition RollupMin interval). when using aggregates it will
211-
return one series per aggregate function, the `Aggregator` label will be added to that series with the function name.
213+
return one series per aggregate function, the `Aggregate` label will be added to that series with the function name.
212214

213215
In some cases we would like to retrieve overlapping aggregates instead of fixed interval ones, e.g. stats for last 1hr, 6hr, 24hr
214216
the `SelectOverlap()` call adds the `win` integer array ([]int) which allow specifying the requested windows. the windows are

Diff for: examples/nuclio/ingest/ingest_example.go

+10-7
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ import (
1212
)
1313

1414
// Configuration
15-
// Note: the TSDB (path) must be first created using the CLI or API
16-
// the user must also define the v3io data binding in the nuclio function with path, username, password and name it db0
15+
// Note: the TSDB instance (`path`) must first be created using the CLI or API.
16+
// The user must also define the V3IO data binding in the Nuclio function - including path, username, and password - and name it "db0".
1717
var tsdbConfig = `
1818
path: "pmetric"
1919
`
2020

21-
// example event
21+
// Example event
2222
const pushEvent = `
2323
{
2424
"Lset": { "__name__":"cpu", "os" : "win", "node" : "xyz123"},
@@ -38,12 +38,15 @@ func Handler(context *nuclio.Context, event nuclio.Event) (interface{}, error) {
3838
}
3939
app := context.UserData.(tsdb.Appender)
4040

41-
// if time is not specified assume "now"
41+
// If time isn't specified, assume "now" (default)
4242
if sample.Time == "" {
4343
sample.Time = "now"
4444
}
4545

46-
// convert time string to time int, string can be: now, now-2h, int (unix milisec time), or RFC3339 date string
46+
// Convert a time string to a Unix timestamp in milliseconds integer.
47+
// The input time string can be of the format "now", "now-[0-9]+[mdh]"
48+
// (for example, "now-2h"), "<Unix timestamp in milliseconds>", or
49+
// "<RFC3339 time>" (for example, "2018-09-26T14:10:20Z").
4750
t, err := utils.Str2unixTime(sample.Time)
4851
if err != nil {
4952
return "", err
@@ -54,15 +57,15 @@ func Handler(context *nuclio.Context, event nuclio.Event) (interface{}, error) {
5457
return "", err
5558
}
5659

57-
// InitContext runs only once when the function runtime starts
60+
// InitContext runs only once, when the function runtime starts
5861
func InitContext(context *nuclio.Context) error {
5962

6063
var err error
6164
defer adapterMtx.Unlock()
6265
adapterMtx.Lock()
6366

6467
if adapter == nil {
65-
// create adapter once for all contexts
68+
// Create an adapter once for all contexts
6669
cfg, _ := config.GetOrLoadFromData([]byte(tsdbConfig))
6770
data := context.DataBinding["db0"].(*v3io.Container)
6871
adapter, err = tsdb.NewV3ioAdapter(cfg, data, context.Logger)

Diff for: examples/nuclio/query/query_example.go

+22-18
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,25 @@ path: "pmetric"
1919
`
2020

2121
type tsdbQuery struct {
22-
Name string
23-
Aggregators []string
24-
Step string
25-
Filter string
26-
From string
27-
To string
28-
Last string
22+
Name string
23+
Aggregates []string
24+
Step string
25+
Filter string
26+
From string
27+
To string
28+
Last string
2929
}
3030

31-
// example query event
31+
// Example query event
3232
const queryEvent = `
3333
{
3434
"Name": "cpu",
3535
"Last":"2h"
3636
}
3737
`
3838

39-
// Note: the user must define the v3io data binding in the nuclio function with path, username, password and name it db0
39+
// Note: The user must define a "db0" V3IO data binding in the nuclio function
40+
// with path, username, and password.
4041

4142
func Handler(context *nuclio.Context, event nuclio.Event) (interface{}, error) {
4243

@@ -46,30 +47,33 @@ func Handler(context *nuclio.Context, event nuclio.Event) (interface{}, error) {
4647
return nil, err
4748
}
4849

49-
// convert string times (unix or RFC3339 or relative like now-2h) to unix milisec times
50+
// Convert time strings to Unix timestamp in milliseconds integers.
51+
// The input time string can be of the format "now", "now-[0-9]+[mdh]"
52+
// (for example, "now-2h"), "<Unix timestamp in milliseconds>", or
53+
// "<RFC3339 time>" (for example, "2018-09-26T14:10:20Z").
5054
from, to, step, err := utils.GetTimeFromRange(query.From, query.To, query.Last, query.Step)
5155
if err != nil {
52-
return nil, errors.Wrap(err, "Error parsing query time range")
56+
return nil, errors.Wrap(err, "Error parsing query time range.")
5357
}
5458

55-
// Create TSDB Querier
59+
// Create a TSDB Querier
5660
context.Logger.DebugWith("Query", "params", query)
5761
adapter := context.UserData.(*tsdb.V3ioAdapter)
5862
qry, err := adapter.Querier(nil, from, to)
5963
if err != nil {
6064
return nil, errors.Wrap(err, "Failed to initialize Querier")
6165
}
6266

63-
// Select Query to get back a series set iterator
64-
set, err := qry.Select(query.Name, strings.Join(query.Aggregators, ","), step, query.Filter)
67+
// Select a query to get back a series-set iterator
68+
set, err := qry.Select(query.Name, strings.Join(query.Aggregates, ","), step, query.Filter)
6569
if err != nil {
6670
return nil, errors.Wrap(err, "Select Failed")
6771
}
6872

69-
// convert SeriesSet to Json (Grafana simpleJson format)
73+
// Convert a SeriesSet to a JSON object (Grafana simpleJson format)
7074
f, err := formatter.NewFormatter("json", nil)
7175
if err != nil {
72-
return nil, errors.Wrap(err, "failed to start json formatter")
76+
return nil, errors.Wrap(err, "Failed to start the JSON formatter.")
7377
}
7478

7579
var b bytes.Buffer
@@ -78,7 +82,7 @@ func Handler(context *nuclio.Context, event nuclio.Event) (interface{}, error) {
7882
return b.String(), err
7983
}
8084

81-
// InitContext runs only once when the function runtime starts
85+
// InitContext runs only once, when the function runtime starts
8286
func InitContext(context *nuclio.Context) error {
8387
cfg, _ := config.GetOrLoadFromData([]byte(tsdbConfig))
8488
data := context.DataBinding["db0"].(*v3io.Container)
@@ -87,7 +91,7 @@ func InitContext(context *nuclio.Context) error {
8791
return err
8892
}
8993

90-
// Store adapter in user cache
94+
// Store the adapter in the user-data cache
9195
context.UserData = adapter
9296
return nil
9397
}

Diff for: examples/v3io.yaml.template renamed to examples/v3io-tsdb-config.yaml.template

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# File: v3io.yaml.template
1+
# File: v3io-tsdb-config.yaml
22
# Description: Template of a V3IO TSDB Configuration File
33

44
# TODO: In your configuration file, delete the configuration keys that you
@@ -14,13 +14,11 @@ webApiEndpoint: "<IP address/host name>:8081"
1414
# Example: "bigdata"
1515
container: "<container name>"
1616

17-
# Logging verbosity level
17+
# Log level
1818
# Valid values: "debug" | "info" | "warn" | "error"
19-
# Default value: "debug"
20-
verbose: "warn"
19+
logLevel: "warn"
2120

2221
# Authentication credentials for the web-API service
23-
# Username
2422
username: "<username>"
25-
# Password
26-
password: "<password>"
23+
password: "<password>"
24+

Diff for: internal/pkg/performance/metrics.go

+35-21
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,13 @@ import (
1414
"time"
1515
)
1616

17+
const (
18+
reservoirSize = 100
19+
)
20+
1721
var instance *MetricReporter
1822
var once sync.Once
23+
var sampleInstance metrics.Sample
1924

2025
const (
2126
STDOUT = "stdout"
@@ -59,6 +64,7 @@ func ReporterInstance(writeTo string, reportPeriodically bool, reportIntervalSec
5964
writer = os.Stdout
6065
}
6166

67+
sampleInstance = metrics.NewUniformSample(reservoirSize)
6268
instance = newMetricReporter(writer, reportPeriodically, reportIntervalSeconds, reportOnShutdown)
6369
})
6470
return instance
@@ -76,7 +82,7 @@ func (mr *MetricReporter) Start() error {
7682
mr.lock.Lock()
7783
defer mr.lock.Unlock()
7884

79-
if !mr.running {
85+
if mr.isEnabled() && !mr.running {
8086
mr.running = true
8187
} else {
8288
return errors.Errorf("metric reporter is already running.")
@@ -103,36 +109,33 @@ func (mr *MetricReporter) Stop() error {
103109
return nil
104110
}
105111

106-
func (mr *MetricReporter) GetTimer(name string) (metrics.Timer, error) {
107-
if mr.running {
108-
return metrics.GetOrRegisterTimer(name, mr.registry), nil
112+
func (mr *MetricReporter) WithTimer(name string, body func()) {
113+
if mr.isRunning() {
114+
timer := metrics.GetOrRegisterTimer(name, mr.registry)
115+
timer.Time(body)
109116
} else {
110-
return nil, errors.Errorf("failed to create timer '%s'. Reason: metric reporter in not running", name)
117+
body()
111118
}
112119
}
113120

114-
func (mr *MetricReporter) GetCounter(name string) (metrics.Counter, error) {
115-
if mr.running {
116-
return metrics.GetOrRegisterCounter(name, mr.registry), nil
117-
} else {
118-
return nil, errors.Errorf("failed to create counter '%s'. Reason: metric reporter in not running", name)
121+
func (mr *MetricReporter) IncrementCounter(name string, count int64) {
122+
if mr.isRunning() {
123+
counter := metrics.GetOrRegisterCounter(name, mr.registry)
124+
counter.Inc(count)
119125
}
120126
}
121127

122-
func (mr *MetricReporter) GetMeter(name string) (metrics.Meter, error) {
123-
if mr.running {
124-
return metrics.GetOrRegisterMeter(name, mr.registry), nil
125-
} else {
126-
return nil, errors.Errorf("failed to create meter '%s'. Reason: metric reporter in not running", name)
128+
func (mr *MetricReporter) UpdateMeter(name string, count int64) {
129+
if mr.isRunning() {
130+
meter := metrics.GetOrRegisterMeter(name, mr.registry)
131+
meter.Mark(count)
127132
}
128133
}
129134

130-
func (mr *MetricReporter) GetHistogram(name string, reservoirSize int) (metrics.Histogram, error) {
131-
if mr.running {
132-
sample := metrics.NewUniformSample(reservoirSize)
133-
return metrics.GetOrRegisterHistogram(name, mr.registry, sample), nil
134-
} else {
135-
return nil, errors.Errorf("failed to create histogram '%s'. Reason: metric reporter in not running", name)
135+
func (mr *MetricReporter) UpdateHistogram(name string, value int64) {
136+
if mr.isRunning() {
137+
histogram := metrics.GetOrRegisterHistogram(name, mr.registry, sampleInstance)
138+
histogram.Update(value)
136139
}
137140
}
138141

@@ -182,3 +185,14 @@ func newMetricReporter(outputWriter io.Writer, reportPeriodically bool, reportIn
182185

183186
return &reporter
184187
}
188+
189+
func (mr *MetricReporter) isEnabled() bool {
190+
return mr.reportOnShutdown || mr.reportPeriodically
191+
}
192+
193+
func (mr *MetricReporter) isRunning() bool {
194+
mr.lock.Lock()
195+
defer mr.lock.Unlock()
196+
197+
return mr.running
198+
}

0 commit comments

Comments
 (0)