mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
Merge pull request #573 from prometheus/beorn7/fingerprint
The big and scary fingerprint update.
This commit is contained in:
commit
0a1678b5f1
16
Godeps/Godeps.json
generated
16
Godeps/Godeps.json
generated
|
@ -29,23 +29,23 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/prometheus/client_golang/extraction",
|
"ImportPath": "github.com/prometheus/client_golang/extraction",
|
||||||
"Comment": "0.2.0-3-ga6c5e0f",
|
"Comment": "0.3.0",
|
||||||
"Rev": "a6c5e0f955686b0e7bbfd791edecfc65aa72593a"
|
"Rev": "dbbb6c9e1dbb3bf19d0f9a61baa852cbfcee1896"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/prometheus/client_golang/model",
|
"ImportPath": "github.com/prometheus/client_golang/model",
|
||||||
"Comment": "0.2.0-3-ga6c5e0f",
|
"Comment": "0.3.0",
|
||||||
"Rev": "a6c5e0f955686b0e7bbfd791edecfc65aa72593a"
|
"Rev": "dbbb6c9e1dbb3bf19d0f9a61baa852cbfcee1896"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/prometheus/client_golang/prometheus",
|
"ImportPath": "github.com/prometheus/client_golang/prometheus",
|
||||||
"Comment": "0.2.0-3-ga6c5e0f",
|
"Comment": "0.3.0",
|
||||||
"Rev": "a6c5e0f955686b0e7bbfd791edecfc65aa72593a"
|
"Rev": "dbbb6c9e1dbb3bf19d0f9a61baa852cbfcee1896"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/prometheus/client_golang/text",
|
"ImportPath": "github.com/prometheus/client_golang/text",
|
||||||
"Comment": "0.2.0-3-ga6c5e0f",
|
"Comment": "0.3.0",
|
||||||
"Rev": "a6c5e0f955686b0e7bbfd791edecfc65aa72593a"
|
"Rev": "dbbb6c9e1dbb3bf19d0f9a61baa852cbfcee1896"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/prometheus/client_model/go",
|
"ImportPath": "github.com/prometheus/client_model/go",
|
||||||
|
|
|
@ -18,9 +18,11 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/matttproud/golang_protobuf_extensions/ext"
|
|
||||||
"github.com/prometheus/client_golang/model"
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/matttproud/golang_protobuf_extensions/ext"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type metricFamilyProcessor struct{}
|
type metricFamilyProcessor struct{}
|
||||||
|
|
34
Godeps/_workspace/src/github.com/prometheus/client_golang/model/metric.go
generated
vendored
34
Godeps/_workspace/src/github.com/prometheus/client_golang/model/metric.go
generated
vendored
|
@ -14,10 +14,8 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/fnv"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -66,37 +64,7 @@ func (m Metric) String() string {
|
||||||
|
|
||||||
// Fingerprint returns a Metric's Fingerprint.
|
// Fingerprint returns a Metric's Fingerprint.
|
||||||
func (m Metric) Fingerprint() Fingerprint {
|
func (m Metric) Fingerprint() Fingerprint {
|
||||||
labelNames := make([]string, 0, len(m))
|
return metricToFingerprint(m)
|
||||||
maxLength := 0
|
|
||||||
|
|
||||||
for labelName, labelValue := range m {
|
|
||||||
labelNames = append(labelNames, string(labelName))
|
|
||||||
if len(labelName) > maxLength {
|
|
||||||
maxLength = len(labelName)
|
|
||||||
}
|
|
||||||
if len(labelValue) > maxLength {
|
|
||||||
maxLength = len(labelValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(labelNames)
|
|
||||||
|
|
||||||
summer := fnv.New64a()
|
|
||||||
buf := make([]byte, maxLength)
|
|
||||||
|
|
||||||
for _, labelName := range labelNames {
|
|
||||||
labelValue := m[LabelName(labelName)]
|
|
||||||
|
|
||||||
copy(buf, labelName)
|
|
||||||
summer.Write(buf[:len(labelName)])
|
|
||||||
|
|
||||||
summer.Write(separator)
|
|
||||||
|
|
||||||
copy(buf, labelValue)
|
|
||||||
summer.Write(buf[:len(labelValue)])
|
|
||||||
}
|
|
||||||
|
|
||||||
return Fingerprint(binary.LittleEndian.Uint64(summer.Sum(nil)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clone returns a copy of the Metric.
|
// Clone returns a copy of the Metric.
|
||||||
|
|
14
Godeps/_workspace/src/github.com/prometheus/client_golang/model/metric_test.go
generated
vendored
14
Godeps/_workspace/src/github.com/prometheus/client_golang/model/metric_test.go
generated
vendored
|
@ -22,7 +22,7 @@ func testMetric(t testing.TB) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
input: Metric{},
|
input: Metric{},
|
||||||
fingerprint: 2676020557754725067,
|
fingerprint: 14695981039346656037,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: Metric{
|
input: Metric{
|
||||||
|
@ -30,31 +30,27 @@ func testMetric(t testing.TB) {
|
||||||
"occupation": "robot",
|
"occupation": "robot",
|
||||||
"manufacturer": "westinghouse",
|
"manufacturer": "westinghouse",
|
||||||
},
|
},
|
||||||
fingerprint: 13260944541294022935,
|
fingerprint: 11310079640881077873,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: Metric{
|
input: Metric{
|
||||||
"x": "y",
|
"x": "y",
|
||||||
},
|
},
|
||||||
fingerprint: 1470933794305433534,
|
fingerprint: 13948396922932177635,
|
||||||
},
|
},
|
||||||
// The following two demonstrate a bug in fingerprinting. They
|
|
||||||
// should not have the same fingerprint with a sane
|
|
||||||
// fingerprinting function. See
|
|
||||||
// https://github.com/prometheus/client_golang/issues/74 .
|
|
||||||
{
|
{
|
||||||
input: Metric{
|
input: Metric{
|
||||||
"a": "bb",
|
"a": "bb",
|
||||||
"b": "c",
|
"b": "c",
|
||||||
},
|
},
|
||||||
fingerprint: 3734646176939799877,
|
fingerprint: 3198632812309449502,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: Metric{
|
input: Metric{
|
||||||
"a": "b",
|
"a": "b",
|
||||||
"bb": "c",
|
"bb": "c",
|
||||||
},
|
},
|
||||||
fingerprint: 3734646176939799877,
|
fingerprint: 5774953389407657638,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
74
Godeps/_workspace/src/github.com/prometheus/client_golang/model/signature.go
generated
vendored
74
Godeps/_workspace/src/github.com/prometheus/client_golang/model/signature.go
generated
vendored
|
@ -63,10 +63,10 @@ func LabelsToSignature(labels map[string]string) uint64 {
|
||||||
hb := getHashAndBuf()
|
hb := getHashAndBuf()
|
||||||
defer putHashAndBuf(hb)
|
defer putHashAndBuf(hb)
|
||||||
|
|
||||||
for k, v := range labels {
|
for labelName, labelValue := range labels {
|
||||||
hb.b.WriteString(k)
|
hb.b.WriteString(labelName)
|
||||||
hb.b.WriteByte(SeparatorByte)
|
hb.b.WriteByte(SeparatorByte)
|
||||||
hb.b.WriteString(v)
|
hb.b.WriteString(labelValue)
|
||||||
hb.h.Write(hb.b.Bytes())
|
hb.h.Write(hb.b.Bytes())
|
||||||
result ^= hb.h.Sum64()
|
result ^= hb.h.Sum64()
|
||||||
hb.h.Reset()
|
hb.h.Reset()
|
||||||
|
@ -75,10 +75,34 @@ func LabelsToSignature(labels map[string]string) uint64 {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// LabelValuesToSignature returns a unique signature (i.e., fingerprint) for the
|
// metricToFingerprint works exactly as LabelsToSignature but takes a Metric as
|
||||||
// values of a given label set.
|
// parameter (rather than a label map) and returns a Fingerprint.
|
||||||
func LabelValuesToSignature(labels map[string]string) uint64 {
|
func metricToFingerprint(m Metric) Fingerprint {
|
||||||
if len(labels) == 0 {
|
if len(m) == 0 {
|
||||||
|
return Fingerprint(emptyLabelSignature)
|
||||||
|
}
|
||||||
|
|
||||||
|
var result uint64
|
||||||
|
hb := getHashAndBuf()
|
||||||
|
defer putHashAndBuf(hb)
|
||||||
|
|
||||||
|
for labelName, labelValue := range m {
|
||||||
|
hb.b.WriteString(string(labelName))
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.b.WriteString(string(labelValue))
|
||||||
|
hb.h.Write(hb.b.Bytes())
|
||||||
|
result ^= hb.h.Sum64()
|
||||||
|
hb.h.Reset()
|
||||||
|
hb.b.Reset()
|
||||||
|
}
|
||||||
|
return Fingerprint(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignatureForLabels works like LabelsToSignature but takes a Metric as
|
||||||
|
// parameter (rather than a label map) and only includes the labels with the
|
||||||
|
// specified LabelNames into the signature calculation.
|
||||||
|
func SignatureForLabels(m Metric, labels LabelNames) uint64 {
|
||||||
|
if len(m) == 0 || len(labels) == 0 {
|
||||||
return emptyLabelSignature
|
return emptyLabelSignature
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,8 +110,10 @@ func LabelValuesToSignature(labels map[string]string) uint64 {
|
||||||
hb := getHashAndBuf()
|
hb := getHashAndBuf()
|
||||||
defer putHashAndBuf(hb)
|
defer putHashAndBuf(hb)
|
||||||
|
|
||||||
for _, v := range labels {
|
for _, label := range labels {
|
||||||
hb.b.WriteString(v)
|
hb.b.WriteString(string(label))
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.b.WriteString(string(m[label]))
|
||||||
hb.h.Write(hb.b.Bytes())
|
hb.h.Write(hb.b.Bytes())
|
||||||
result ^= hb.h.Sum64()
|
result ^= hb.h.Sum64()
|
||||||
hb.h.Reset()
|
hb.h.Reset()
|
||||||
|
@ -95,3 +121,33 @@ func LabelValuesToSignature(labels map[string]string) uint64 {
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SignatureWithoutLabels works like LabelsToSignature but takes a Metric as
|
||||||
|
// parameter (rather than a label map) and excludes the labels with any of the
|
||||||
|
// specified LabelNames from the signature calculation.
|
||||||
|
func SignatureWithoutLabels(m Metric, labels map[LabelName]struct{}) uint64 {
|
||||||
|
if len(m) == 0 {
|
||||||
|
return emptyLabelSignature
|
||||||
|
}
|
||||||
|
|
||||||
|
var result uint64
|
||||||
|
hb := getHashAndBuf()
|
||||||
|
defer putHashAndBuf(hb)
|
||||||
|
|
||||||
|
for labelName, labelValue := range m {
|
||||||
|
if _, exclude := labels[labelName]; exclude {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hb.b.WriteString(string(labelName))
|
||||||
|
hb.b.WriteByte(SeparatorByte)
|
||||||
|
hb.b.WriteString(string(labelValue))
|
||||||
|
hb.h.Write(hb.b.Bytes())
|
||||||
|
result ^= hb.h.Sum64()
|
||||||
|
hb.h.Reset()
|
||||||
|
hb.b.Reset()
|
||||||
|
}
|
||||||
|
if result == 0 {
|
||||||
|
return emptyLabelSignature
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
180
Godeps/_workspace/src/github.com/prometheus/client_golang/model/signature_test.go
generated
vendored
180
Godeps/_workspace/src/github.com/prometheus/client_golang/model/signature_test.go
generated
vendored
|
@ -18,7 +18,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testLabelsToSignature(t testing.TB) {
|
func TestLabelsToSignature(t *testing.T) {
|
||||||
var scenarios = []struct {
|
var scenarios = []struct {
|
||||||
in map[string]string
|
in map[string]string
|
||||||
out uint64
|
out uint64
|
||||||
|
@ -42,57 +42,112 @@ func testLabelsToSignature(t testing.TB) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLabelToSignature(t *testing.T) {
|
func TestMetricToFingerprint(t *testing.T) {
|
||||||
testLabelsToSignature(t)
|
var scenarios = []struct {
|
||||||
}
|
in Metric
|
||||||
|
out Fingerprint
|
||||||
func TestEmptyLabelSignature(t *testing.T) {
|
}{
|
||||||
input := []map[string]string{nil, {}}
|
{
|
||||||
|
in: Metric{},
|
||||||
var ms runtime.MemStats
|
out: 14695981039346656037,
|
||||||
runtime.ReadMemStats(&ms)
|
},
|
||||||
|
{
|
||||||
alloc := ms.Alloc
|
in: Metric{"name": "garland, briggs", "fear": "love is not enough"},
|
||||||
|
out: 12952432476264840823,
|
||||||
for _, labels := range input {
|
},
|
||||||
LabelsToSignature(labels)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.ReadMemStats(&ms)
|
for i, scenario := range scenarios {
|
||||||
|
actual := metricToFingerprint(scenario.in)
|
||||||
|
|
||||||
if got := ms.Alloc; alloc != got {
|
if actual != scenario.out {
|
||||||
t.Fatal("expected LabelsToSignature with empty labels not to perform allocations")
|
t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkLabelToSignature(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
testLabelsToSignature(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func benchmarkLabelValuesToSignature(b *testing.B, l map[string]string, e uint64) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
if a := LabelValuesToSignature(l); a != e {
|
|
||||||
b.Fatalf("expected signature of %d for %s, got %d", e, l, a)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkLabelValuesToSignatureScalar(b *testing.B) {
|
func TestSignatureForLabels(t *testing.T) {
|
||||||
benchmarkLabelValuesToSignature(b, nil, 14695981039346656037)
|
var scenarios = []struct {
|
||||||
|
in Metric
|
||||||
|
labels LabelNames
|
||||||
|
out uint64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
in: Metric{},
|
||||||
|
labels: nil,
|
||||||
|
out: 14695981039346656037,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: Metric{"name": "garland, briggs", "fear": "love is not enough"},
|
||||||
|
labels: LabelNames{"fear", "name"},
|
||||||
|
out: 12952432476264840823,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: Metric{"name": "garland, briggs", "fear": "love is not enough", "foo": "bar"},
|
||||||
|
labels: LabelNames{"fear", "name"},
|
||||||
|
out: 12952432476264840823,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: Metric{"name": "garland, briggs", "fear": "love is not enough"},
|
||||||
|
labels: LabelNames{},
|
||||||
|
out: 14695981039346656037,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: Metric{"name": "garland, briggs", "fear": "love is not enough"},
|
||||||
|
labels: nil,
|
||||||
|
out: 14695981039346656037,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, scenario := range scenarios {
|
||||||
|
actual := SignatureForLabels(scenario.in, scenario.labels)
|
||||||
|
|
||||||
|
if actual != scenario.out {
|
||||||
|
t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkLabelValuesToSignatureSingle(b *testing.B) {
|
func TestSignatureWithoutLabels(t *testing.T) {
|
||||||
benchmarkLabelValuesToSignature(b, map[string]string{"first-label": "first-label-value"}, 2653746141194979650)
|
var scenarios = []struct {
|
||||||
}
|
in Metric
|
||||||
|
labels map[LabelName]struct{}
|
||||||
|
out uint64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
in: Metric{},
|
||||||
|
labels: nil,
|
||||||
|
out: 14695981039346656037,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: Metric{"name": "garland, briggs", "fear": "love is not enough"},
|
||||||
|
labels: map[LabelName]struct{}{"fear": struct{}{}, "name": struct{}{}},
|
||||||
|
out: 14695981039346656037,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: Metric{"name": "garland, briggs", "fear": "love is not enough", "foo": "bar"},
|
||||||
|
labels: map[LabelName]struct{}{"foo": struct{}{}},
|
||||||
|
out: 12952432476264840823,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: Metric{"name": "garland, briggs", "fear": "love is not enough"},
|
||||||
|
labels: map[LabelName]struct{}{},
|
||||||
|
out: 12952432476264840823,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: Metric{"name": "garland, briggs", "fear": "love is not enough"},
|
||||||
|
labels: nil,
|
||||||
|
out: 12952432476264840823,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkLabelValuesToSignatureDouble(b *testing.B) {
|
for i, scenario := range scenarios {
|
||||||
benchmarkLabelValuesToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value"}, 8893559499616767364)
|
actual := SignatureWithoutLabels(scenario.in, scenario.labels)
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkLabelValuesToSignatureTriple(b *testing.B) {
|
if actual != scenario.out {
|
||||||
benchmarkLabelValuesToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 1685970066862087833)
|
t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func benchmarkLabelToSignature(b *testing.B, l map[string]string, e uint64) {
|
func benchmarkLabelToSignature(b *testing.B, l map[string]string, e uint64) {
|
||||||
|
@ -118,3 +173,46 @@ func BenchmarkLabelToSignatureDouble(b *testing.B) {
|
||||||
func BenchmarkLabelToSignatureTriple(b *testing.B) {
|
func BenchmarkLabelToSignatureTriple(b *testing.B) {
|
||||||
benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676)
|
benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func benchmarkMetricToFingerprint(b *testing.B, m Metric, e Fingerprint) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
if a := metricToFingerprint(m); a != e {
|
||||||
|
b.Fatalf("expected signature of %d for %s, got %d", e, m, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMetricToFingerprintScalar(b *testing.B) {
|
||||||
|
benchmarkMetricToFingerprint(b, nil, 14695981039346656037)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMetricToFingerprintSingle(b *testing.B) {
|
||||||
|
benchmarkMetricToFingerprint(b, Metric{"first-label": "first-label-value"}, 5147259542624943964)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMetricToFingerprintDouble(b *testing.B) {
|
||||||
|
benchmarkMetricToFingerprint(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value"}, 18269973311206963528)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMetricToFingerprintTriple(b *testing.B) {
|
||||||
|
benchmarkMetricToFingerprint(b, Metric{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEmptyLabelSignature(t *testing.T) {
|
||||||
|
input := []map[string]string{nil, {}}
|
||||||
|
|
||||||
|
var ms runtime.MemStats
|
||||||
|
runtime.ReadMemStats(&ms)
|
||||||
|
|
||||||
|
alloc := ms.Alloc
|
||||||
|
|
||||||
|
for _, labels := range input {
|
||||||
|
LabelsToSignature(labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime.ReadMemStats(&ms)
|
||||||
|
|
||||||
|
if got := ms.Alloc; alloc != got {
|
||||||
|
t.Fatal("expected LabelsToSignature with empty labels not to perform allocations")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1
Godeps/_workspace/src/github.com/prometheus/client_golang/model/timestamp.go
generated
vendored
1
Godeps/_workspace/src/github.com/prometheus/client_golang/model/timestamp.go
generated
vendored
|
@ -88,6 +88,7 @@ func (t Timestamp) String() string {
|
||||||
return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64)
|
return strconv.FormatFloat(float64(t)/float64(second), 'f', -1, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface.
|
||||||
func (t Timestamp) MarshalJSON() ([]byte, error) {
|
func (t Timestamp) MarshalJSON() ([]byte, error) {
|
||||||
return []byte(t.String()), nil
|
return []byte(t.String()), nil
|
||||||
}
|
}
|
||||||
|
|
3
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
3
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/desc.go
generated
vendored
|
@ -11,8 +11,9 @@ import (
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/model"
|
"github.com/prometheus/client_golang/model"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -17,8 +17,10 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewCallbackMetric(desc *prometheus.Desc, callback func() float64) *CallbackMetric {
|
func NewCallbackMetric(desc *prometheus.Desc, callback func() float64) *CallbackMetric {
|
||||||
|
|
|
@ -21,9 +21,11 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleGauge() {
|
func ExampleGauge() {
|
||||||
|
|
3
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/expvar_test.go
generated
vendored
3
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/expvar_test.go
generated
vendored
|
@ -19,8 +19,9 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleExpvarCollector() {
|
func ExampleExpvarCollector() {
|
||||||
|
|
1
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
1
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/histogram.go
generated
vendored
|
@ -21,6 +21,7 @@ import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/model"
|
"github.com/prometheus/client_golang/model"
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
)
|
)
|
||||||
|
|
4
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
4
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/registry.go
generated
vendored
|
@ -35,9 +35,11 @@ import (
|
||||||
|
|
||||||
"bitbucket.org/ww/goautoneg"
|
"bitbucket.org/ww/goautoneg"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/model"
|
"github.com/prometheus/client_golang/model"
|
||||||
"github.com/prometheus/client_golang/text"
|
"github.com/prometheus/client_golang/text"
|
||||||
dto "github.com/prometheus/client_model/go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
4
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
4
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/summary.go
generated
vendored
|
@ -22,8 +22,10 @@ import (
|
||||||
|
|
||||||
"github.com/beorn7/perks/quantile"
|
"github.com/beorn7/perks/quantile"
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/prometheus/client_golang/model"
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A Summary captures individual observations from an event or sample stream and
|
// A Summary captures individual observations from an event or sample stream and
|
||||||
|
|
3
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/value.go
generated
vendored
3
Godeps/_workspace/src/github.com/prometheus/client_golang/prometheus/value.go
generated
vendored
|
@ -20,8 +20,9 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ValueType is an enumeration of metric types that represent a simple value.
|
// ValueType is an enumeration of metric types that represent a simple value.
|
||||||
|
|
5
Godeps/_workspace/src/github.com/prometheus/client_golang/text/bench_test.go
generated
vendored
5
Godeps/_workspace/src/github.com/prometheus/client_golang/text/bench_test.go
generated
vendored
|
@ -16,11 +16,12 @@ package text
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"github.com/matttproud/golang_protobuf_extensions/ext"
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
|
"github.com/matttproud/golang_protobuf_extensions/ext"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Benchmarks to show how much penalty text format parsing actually inflicts.
|
// Benchmarks to show how much penalty text format parsing actually inflicts.
|
||||||
|
|
3
Godeps/_workspace/src/github.com/prometheus/client_golang/text/parse.go
generated
vendored
3
Godeps/_workspace/src/github.com/prometheus/client_golang/text/parse.go
generated
vendored
|
@ -22,9 +22,10 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/prometheus/client_golang/model"
|
"github.com/prometheus/client_golang/model"
|
||||||
dto "github.com/prometheus/client_model/go"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// A stateFn is a function that represents a state in a state machine. By
|
// A stateFn is a function that represents a state in a state machine. By
|
||||||
|
|
2
Godeps/_workspace/src/github.com/prometheus/client_golang/text/parse_test.go
generated
vendored
2
Godeps/_workspace/src/github.com/prometheus/client_golang/text/parse_test.go
generated
vendored
|
@ -385,7 +385,7 @@ request_duration_microseconds_count 2693
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, scenario := range scenarios {
|
for i, scenario := range scenarios {
|
||||||
|
|
1
Godeps/_workspace/src/github.com/prometheus/client_golang/text/proto.go
generated
vendored
1
Godeps/_workspace/src/github.com/prometheus/client_golang/text/proto.go
generated
vendored
|
@ -19,6 +19,7 @@ import (
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/matttproud/golang_protobuf_extensions/ext"
|
"github.com/matttproud/golang_protobuf_extensions/ext"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/fnv"
|
|
||||||
"math"
|
"math"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -383,23 +382,6 @@ func (node *ScalarFunctionCall) Eval(timestamp clientmodel.Timestamp) clientmode
|
||||||
return node.function.callFn(timestamp, node.args).(clientmodel.SampleValue)
|
return node.function.callFn(timestamp, node.args).(clientmodel.SampleValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashForLabels returns a hash value taken from the label/value pairs of the
|
|
||||||
// specified labels in the metric.
|
|
||||||
func hashForLabels(metric clientmodel.Metric, labels clientmodel.LabelNames) uint64 {
|
|
||||||
var result uint64
|
|
||||||
s := fnv.New64a()
|
|
||||||
|
|
||||||
for _, label := range labels {
|
|
||||||
s.Write([]byte(label))
|
|
||||||
s.Write([]byte{clientmodel.SeparatorByte})
|
|
||||||
s.Write([]byte(metric[label]))
|
|
||||||
result ^= s.Sum64()
|
|
||||||
s.Reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// EvalVectorInstant evaluates a VectorNode with an instant query.
|
// EvalVectorInstant evaluates a VectorNode with an instant query.
|
||||||
func EvalVectorInstant(node VectorNode, timestamp clientmodel.Timestamp, storage local.Storage, queryStats *stats.TimerGroup) (Vector, error) {
|
func EvalVectorInstant(node VectorNode, timestamp clientmodel.Timestamp, storage local.Storage, queryStats *stats.TimerGroup) (Vector, error) {
|
||||||
totalEvalTimer := queryStats.GetTimer(stats.TotalEvalTime).Start()
|
totalEvalTimer := queryStats.GetTimer(stats.TotalEvalTime).Start()
|
||||||
|
@ -503,7 +485,7 @@ func (node *VectorAggregation) Eval(timestamp clientmodel.Timestamp) Vector {
|
||||||
vector := node.vector.Eval(timestamp)
|
vector := node.vector.Eval(timestamp)
|
||||||
result := map[uint64]*groupedAggregation{}
|
result := map[uint64]*groupedAggregation{}
|
||||||
for _, sample := range vector {
|
for _, sample := range vector {
|
||||||
groupingKey := hashForLabels(sample.Metric.Metric, node.groupBy)
|
groupingKey := clientmodel.SignatureForLabels(sample.Metric.Metric, node.groupBy)
|
||||||
if groupedResult, ok := result[groupingKey]; ok {
|
if groupedResult, ok := result[groupingKey]; ok {
|
||||||
if node.keepExtraLabels {
|
if node.keepExtraLabels {
|
||||||
groupedResult.labels = labelIntersection(groupedResult.labels, sample.Metric)
|
groupedResult.labels = labelIntersection(groupedResult.labels, sample.Metric)
|
||||||
|
@ -879,7 +861,7 @@ func (node *VectorArithExpr) evalVectors(timestamp clientmodel.Timestamp, lhs, r
|
||||||
metric := node.resultMetric(ls, rs)
|
metric := node.resultMetric(ls, rs)
|
||||||
// Check if the same label set has been added for a many-to-one matching before.
|
// Check if the same label set has been added for a many-to-one matching before.
|
||||||
if node.matchCardinality == MatchManyToOne || node.matchCardinality == MatchOneToMany {
|
if node.matchCardinality == MatchManyToOne || node.matchCardinality == MatchOneToMany {
|
||||||
insHash := hashForLabels(metric.Metric, node.includeLabels)
|
insHash := clientmodel.SignatureForLabels(metric.Metric, node.includeLabels)
|
||||||
if ihs, exists := added[hash]; exists {
|
if ihs, exists := added[hash]; exists {
|
||||||
for _, ih := range ihs {
|
for _, ih := range ihs {
|
||||||
if ih == insHash {
|
if ih == insHash {
|
||||||
|
@ -971,7 +953,7 @@ func (node *VectorArithExpr) hashForMetric(metric clientmodel.Metric) uint64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hashForLabels(metric, labels)
|
return clientmodel.SignatureForLabels(metric, labels)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eval implements the MatrixNode interface and returns the value of
|
// Eval implements the MatrixNode interface and returns the value of
|
||||||
|
|
|
@ -504,7 +504,7 @@ func histogramQuantileImpl(timestamp clientmodel.Timestamp, args []Node) interfa
|
||||||
q := args[0].(ScalarNode).Eval(timestamp)
|
q := args[0].(ScalarNode).Eval(timestamp)
|
||||||
inVec := args[1].(VectorNode).Eval(timestamp)
|
inVec := args[1].(VectorNode).Eval(timestamp)
|
||||||
outVec := Vector{}
|
outVec := Vector{}
|
||||||
fpToMetricWithBuckets := map[clientmodel.Fingerprint]*metricWithBuckets{}
|
signatureToMetricWithBuckets := map[uint64]*metricWithBuckets{}
|
||||||
for _, el := range inVec {
|
for _, el := range inVec {
|
||||||
upperBound, err := strconv.ParseFloat(
|
upperBound, err := strconv.ParseFloat(
|
||||||
string(el.Metric.Metric[clientmodel.BucketLabel]), 64,
|
string(el.Metric.Metric[clientmodel.BucketLabel]), 64,
|
||||||
|
@ -514,18 +514,18 @@ func histogramQuantileImpl(timestamp clientmodel.Timestamp, args []Node) interfa
|
||||||
// TODO(beorn7): Issue a warning somehow.
|
// TODO(beorn7): Issue a warning somehow.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fp := bucketFingerprint(el.Metric.Metric)
|
signature := clientmodel.SignatureWithoutLabels(el.Metric.Metric, excludedLabels)
|
||||||
mb, ok := fpToMetricWithBuckets[fp]
|
mb, ok := signatureToMetricWithBuckets[signature]
|
||||||
if !ok {
|
if !ok {
|
||||||
el.Metric.Delete(clientmodel.BucketLabel)
|
el.Metric.Delete(clientmodel.BucketLabel)
|
||||||
el.Metric.Delete(clientmodel.MetricNameLabel)
|
el.Metric.Delete(clientmodel.MetricNameLabel)
|
||||||
mb = &metricWithBuckets{el.Metric, nil}
|
mb = &metricWithBuckets{el.Metric, nil}
|
||||||
fpToMetricWithBuckets[fp] = mb
|
signatureToMetricWithBuckets[signature] = mb
|
||||||
}
|
}
|
||||||
mb.buckets = append(mb.buckets, bucket{upperBound, el.Value})
|
mb.buckets = append(mb.buckets, bucket{upperBound, el.Value})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mb := range fpToMetricWithBuckets {
|
for _, mb := range signatureToMetricWithBuckets {
|
||||||
outVec = append(outVec, &Sample{
|
outVec = append(outVec, &Sample{
|
||||||
Metric: mb.metric,
|
Metric: mb.metric,
|
||||||
Value: clientmodel.SampleValue(quantile(q, mb.buckets)),
|
Value: clientmodel.SampleValue(quantile(q, mb.buckets)),
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
package ast
|
package ast
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"hash/fnv"
|
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
@ -24,6 +22,13 @@ import (
|
||||||
|
|
||||||
// Helpers to calculate quantiles.
|
// Helpers to calculate quantiles.
|
||||||
|
|
||||||
|
// excludedLabels are the labels to exclude from signature calculation for
|
||||||
|
// quantiles.
|
||||||
|
var excludedLabels = map[clientmodel.LabelName]struct{}{
|
||||||
|
clientmodel.MetricNameLabel: struct{}{},
|
||||||
|
clientmodel.BucketLabel: struct{}{},
|
||||||
|
}
|
||||||
|
|
||||||
type bucket struct {
|
type bucket struct {
|
||||||
upperBound float64
|
upperBound float64
|
||||||
count clientmodel.SampleValue
|
count clientmodel.SampleValue
|
||||||
|
@ -99,46 +104,3 @@ func quantile(q clientmodel.SampleValue, buckets buckets) float64 {
|
||||||
}
|
}
|
||||||
return bucketStart + (bucketEnd-bucketStart)*float64(rank/count)
|
return bucketStart + (bucketEnd-bucketStart)*float64(rank/count)
|
||||||
}
|
}
|
||||||
|
|
||||||
// bucketFingerprint works like the Fingerprint method of Metric, but ignores
|
|
||||||
// the name and the bucket label.
|
|
||||||
func bucketFingerprint(m clientmodel.Metric) clientmodel.Fingerprint {
|
|
||||||
numLabels := 0
|
|
||||||
if len(m) > 2 {
|
|
||||||
numLabels = len(m) - 2
|
|
||||||
}
|
|
||||||
labelNames := make([]string, 0, numLabels)
|
|
||||||
maxLength := 0
|
|
||||||
|
|
||||||
for labelName, labelValue := range m {
|
|
||||||
if labelName == clientmodel.MetricNameLabel || labelName == clientmodel.BucketLabel {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
labelNames = append(labelNames, string(labelName))
|
|
||||||
if len(labelName) > maxLength {
|
|
||||||
maxLength = len(labelName)
|
|
||||||
}
|
|
||||||
if len(labelValue) > maxLength {
|
|
||||||
maxLength = len(labelValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Strings(labelNames)
|
|
||||||
|
|
||||||
summer := fnv.New64a()
|
|
||||||
buf := make([]byte, maxLength)
|
|
||||||
|
|
||||||
for _, labelName := range labelNames {
|
|
||||||
labelValue := m[clientmodel.LabelName(labelName)]
|
|
||||||
|
|
||||||
copy(buf, labelName)
|
|
||||||
summer.Write(buf[:len(labelName)])
|
|
||||||
summer.Write([]byte{clientmodel.SeparatorByte})
|
|
||||||
|
|
||||||
copy(buf, labelValue)
|
|
||||||
summer.Write(buf[:len(labelValue)])
|
|
||||||
summer.Write([]byte{clientmodel.SeparatorByte})
|
|
||||||
}
|
|
||||||
|
|
||||||
return clientmodel.Fingerprint(binary.LittleEndian.Uint64(summer.Sum(nil)))
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,9 +18,12 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -36,6 +39,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// Version of the storage as it can be found in the version file.
|
||||||
|
// Increment to protect against incompatible changes.
|
||||||
|
Version = 1
|
||||||
|
versionFileName = "VERSION"
|
||||||
|
|
||||||
seriesFileSuffix = ".db"
|
seriesFileSuffix = ".db"
|
||||||
seriesTempFileSuffix = ".db.tmp"
|
seriesTempFileSuffix = ".db.tmp"
|
||||||
seriesDirNameLen = 2 // How many bytes of the fingerprint in dir name.
|
seriesDirNameLen = 2 // How many bytes of the fingerprint in dir name.
|
||||||
|
@ -114,10 +122,42 @@ type persistence struct {
|
||||||
|
|
||||||
// newPersistence returns a newly allocated persistence backed by local disk storage, ready to use.
|
// newPersistence returns a newly allocated persistence backed by local disk storage, ready to use.
|
||||||
func newPersistence(basePath string, chunkLen int, dirty bool) (*persistence, error) {
|
func newPersistence(basePath string, chunkLen int, dirty bool) (*persistence, error) {
|
||||||
if err := os.MkdirAll(basePath, 0700); err != nil {
|
dirtyPath := filepath.Join(basePath, dirtyFileName)
|
||||||
|
versionPath := filepath.Join(basePath, versionFileName)
|
||||||
|
|
||||||
|
if versionData, err := ioutil.ReadFile(versionPath); err == nil {
|
||||||
|
if persistedVersion, err := strconv.Atoi(strings.TrimSpace(string(versionData))); err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot parse content of %s: %s", versionPath, versionData)
|
||||||
|
} else if persistedVersion != Version {
|
||||||
|
return nil, fmt.Errorf("found storage version %d on disk, need version %d - please wipe storage or run a version of Prometheus compatible with storage version %d", persistedVersion, Version, persistedVersion)
|
||||||
|
}
|
||||||
|
} else if os.IsNotExist(err) {
|
||||||
|
// No version file found. Let's create the directory (in case
|
||||||
|
// it's not there yet) and then check if it is actually
|
||||||
|
// empty. If not, we have found an old storage directory without
|
||||||
|
// version file, so we have to bail out.
|
||||||
|
if err := os.MkdirAll(basePath, 0700); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fis, err := ioutil.ReadDir(basePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(fis) > 0 {
|
||||||
|
return nil, fmt.Errorf("could not detect storage version on disk, assuming version 0, need version %d - please wipe storage or run a version of Prometheus compatible with storage version 0", Version)
|
||||||
|
}
|
||||||
|
// Finally we can write our own version into a new version file.
|
||||||
|
file, err := os.Create(versionPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
if _, err := fmt.Fprintf(file, "%d\n", Version); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
dirtyPath := filepath.Join(basePath, dirtyFileName)
|
|
||||||
|
|
||||||
fLock, dirtyfileExisted, err := flock.New(dirtyPath)
|
fLock, dirtyfileExisted, err := flock.New(dirtyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue