Skip to content

Commit 6518f23

Browse files
committed
move the management of the lookback interval to the metadata_service
Signed-off-by: Augustin Husson <husson.augustin@gmail.com>
1 parent e8a1aa1 commit 6518f23

File tree

11 files changed

+103
-61
lines changed

11 files changed

+103
-61
lines changed

cmd/promql-langserver/promql-langserver.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"log"
2121
"net/http"
2222
"os"
23+
"time"
2324

2425
kitlog "github.com/go-kit/kit/log"
2526
"github.com/prometheus-community/promql-langserver/config"
@@ -41,7 +42,7 @@ func main() {
4142
}
4243
if conf.RESTAPIPort != 0 {
4344
fmt.Fprintln(os.Stderr, "REST API: Listening on port ", conf.RESTAPIPort)
44-
prometheusClient, err := promClient.NewClient(conf.PrometheusURL)
45+
prometheusClient, err := promClient.NewClient(conf.PrometheusURL, time.Duration(conf.MetadataLookbackInterval))
4546
if err != nil {
4647
log.Fatal(err)
4748
}
@@ -59,7 +60,7 @@ func main() {
5960

6061
logger = kitlog.NewSyncLogger(logger)
6162

62-
handler, err := rest.CreateInstHandler(context.Background(), prometheusClient, logger, config.MetadataLookbackInterval)
63+
handler, err := rest.CreateInstHandler(context.Background(), prometheusClient, logger)
6364
if err != nil {
6465
log.Fatal(err)
6566
}

config/config.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ import (
1818
"net/url"
1919
"os"
2020
"strconv"
21+
"time"
2122

2223
"github.com/kelseyhightower/envconfig"
24+
"github.com/prometheus/common/model"
2325
"gopkg.in/yaml.v3"
2426
)
2527

28+
const defaultInterval = model.Duration(12 * 3600 * time.Second)
29+
2630
// ReadConfig gets the GlobalConfig from a configFile (that is a path to the file).
2731
func ReadConfig(configFile string) (*Config, error) {
2832
if len(configFile) == 0 {
@@ -70,6 +74,8 @@ type Config struct {
7074
LogFormat LogFormat `yaml:"log_format"`
7175
PrometheusURL string `yaml:"prometheus_url"`
7276
RESTAPIPort uint64 `yaml:"rest_api_port"`
77+
// MetadataLookbackInterval is the time in second used to retrieve label and metrics from Prometheus
78+
MetadataLookbackInterval model.Duration `yaml:"metadata_lookback_interval"`
7379
}
7480

7581
// UnmarshalYAML overrides a function used internally by the yaml.v3 lib.
@@ -94,7 +100,8 @@ func (c *Config) unmarshalENV() error {
94100
PrometheusURL string
95101
// the envconfig lib is not able to convert an empty string to the value 0
96102
// so we have to convert it manually
97-
RESTAPIPort string
103+
RESTAPIPort string
104+
MetadataLookbackInterval string
98105
}{}
99106
if err := envconfig.Process(prefix, conf); err != nil {
100107
return err
@@ -106,6 +113,13 @@ func (c *Config) unmarshalENV() error {
106113
return parseError
107114
}
108115
}
116+
if len(conf.MetadataLookbackInterval) > 0 {
117+
var parseError error
118+
c.MetadataLookbackInterval, parseError = model.ParseDuration(conf.MetadataLookbackInterval)
119+
if parseError != nil {
120+
return parseError
121+
}
122+
}
109123
c.ActivateRPCLog = conf.ActivateRPCLog
110124
c.PrometheusURL = conf.PrometheusURL
111125
c.LogFormat = LogFormat(conf.LogFormat)
@@ -129,5 +143,9 @@ func (c *Config) Validate() error {
129143
c.LogFormat = TextFormat
130144
}
131145

146+
if c.MetadataLookbackInterval <= 0 {
147+
c.MetadataLookbackInterval = defaultInterval
148+
}
149+
132150
return nil
133151
}

config/config_test.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,26 @@ func TestUnmarshalENV(t *testing.T) {
3030
title: "empty config",
3131
variables: map[string]string{},
3232
expected: &Config{
33-
ActivateRPCLog: false,
34-
LogFormat: TextFormat,
33+
ActivateRPCLog: false,
34+
LogFormat: TextFormat,
35+
MetadataLookbackInterval: defaultInterval,
3536
},
3637
},
3738
{
3839
title: "full config",
3940
variables: map[string]string{
40-
"LANGSERVER_ACTIVATERPCLOG": "true",
41-
"LANGSERVER_PROMETHEUSURL": "http://localhost:9090",
42-
"LANGSERVER_RESTAPIPORT": "8080",
43-
"LANGSERVER_LOGFORMAT": "json",
41+
"LANGSERVER_ACTIVATERPCLOG": "true",
42+
"LANGSERVER_PROMETHEUSURL": "http://localhost:9090",
43+
"LANGSERVER_RESTAPIPORT": "8080",
44+
"LANGSERVER_LOGFORMAT": "json",
4445
"LANGSERVER_METADATALOOKBACKINTERVAL": "1w",
4546
},
4647
expected: &Config{
47-
ActivateRPCLog: true,
48-
PrometheusURL: "http://localhost:9090",
49-
RESTAPIPort: 8080,
50-
LogFormat: JSONFormat,
48+
ActivateRPCLog: true,
49+
PrometheusURL: "http://localhost:9090",
50+
RESTAPIPort: 8080,
51+
LogFormat: JSONFormat,
52+
MetadataLookbackInterval: 604800000000000,
5153
},
5254
},
5355
}

langserver/completion.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"sort"
2121
"strconv"
2222
"strings"
23-
"time"
2423

2524
"github.com/pkg/errors"
2625

@@ -312,7 +311,7 @@ func (s *server) completeLabel(ctx context.Context, completions *[]protocol.Comp
312311
if vs != nil {
313312
metricName = vs.Name
314313
}
315-
allNames, err := s.metadataService.LabelNames(ctx, metricName, time.Now().Add(time.Duration(-1*s.config.MetadataLookbackInterval)), time.Now())
314+
allNames, err := s.metadataService.LabelNames(ctx, metricName)
316315
if err != nil {
317316
// nolint: errcheck
318317
s.client.LogMessage(s.lifetime, &protocol.LogMessageParams{
@@ -355,7 +354,7 @@ OUTER:
355354

356355
// nolint: funlen
357356
func (s *server) completeLabelValue(ctx context.Context, completions *[]protocol.CompletionItem, location *cache.Location, labelName string) error {
358-
labelValues, err := s.metadataService.LabelValues(ctx, labelName, time.Now().Add(time.Duration(-1*s.config.MetadataLookbackInterval)), time.Now())
357+
labelValues, err := s.metadataService.LabelValues(ctx, labelName)
359358
if err != nil {
360359
// nolint: errcheck
361360
s.client.LogMessage(s.lifetime, &protocol.LogMessageParams{

langserver/config.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ import (
1717
"context"
1818
"fmt"
1919
"net/url"
20+
"time"
2021

2122
"github.com/prometheus-community/promql-langserver/internal/vendored/go-tools/lsp/protocol"
23+
"github.com/prometheus/common/model"
2224
)
2325

2426
// DidChangeConfiguration is required by the protocol.Server interface.
@@ -67,13 +69,13 @@ func (s *server) DidChangeConfiguration(ctx context.Context, params *protocol.Di
6769
})
6870
}
6971

70-
/* if err := s.setMetadataLookbackIntervalFromChangeConfiguration(config); err != nil {
72+
if err := s.setMetadataLookbackInterval(config); err != nil {
7173
// nolint: errcheck
7274
s.client.LogMessage(ctx, &protocol.LogMessageParams{
7375
Type: protocol.Info,
7476
Message: err.Error(),
7577
})
76-
}*/
78+
}
7779
return nil
7880
}
7981

@@ -101,13 +103,13 @@ func (s *server) connectPrometheus(url string) error {
101103
return nil
102104
}
103105

104-
/*func (s *server) setMetadataLookbackIntervalFromChangeConfiguration(settings map[string]string) error {
106+
func (s *server) setMetadataLookbackInterval(settings map[string]string) error {
105107
if interval, ok := settings["metadataLookbackInterval"]; ok {
106108
duration, err := model.ParseDuration(interval)
107109
if err != nil {
108110
return err
109111
}
110-
s.config.MetadataLookbackInterval = duration
112+
s.metadataService.SetLookbackInterval(time.Duration(duration))
111113
}
112114
return nil
113-
}*/
115+
}

langserver/server.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"net"
2828
"os"
2929
"sync"
30+
"time"
3031

3132
"github.com/prometheus-community/promql-langserver/config"
3233
promClient "github.com/prometheus-community/promql-langserver/prometheus"
@@ -136,7 +137,7 @@ func ServerFromStream(ctx context.Context, stream jsonrpc2.Stream, conf *config.
136137

137138
// In order to have an error message in the IDE/editor, we are going to set the prometheusURL in the method server#Initialized.
138139
s.prometheusURL = conf.PrometheusURL
139-
prometheusClient, err := promClient.NewClient("")
140+
prometheusClient, err := promClient.NewClient("", time.Duration(conf.MetadataLookbackInterval))
140141
if err != nil {
141142
// nolint: errcheck
142143
s.client.ShowMessage(s.lifetime, &protocol.ShowMessageParams{

prometheus/compatible.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
type compatibleHTTPClient struct {
2626
MetadataService
2727
prometheusClient v1.API
28+
lookbackInterval time.Duration
2829
}
2930

3031
func (c *compatibleHTTPClient) MetricMetadata(ctx context.Context, metric string) (v1.Metadata, error) {
@@ -46,13 +47,12 @@ func (c *compatibleHTTPClient) AllMetricMetadata(ctx context.Context) (map[strin
4647
return c.prometheusClient.Metadata(ctx, "", "")
4748
}
4849

49-
func (c *compatibleHTTPClient) LabelNames(ctx context.Context, name string,
50-
startTime time.Time, endTime time.Time) ([]string, error) {
50+
func (c *compatibleHTTPClient) LabelNames(ctx context.Context, name string) ([]string, error) {
5151
if len(name) == 0 {
52-
names, _, err := c.prometheusClient.LabelNames(ctx, startTime, endTime)
52+
names, _, err := c.prometheusClient.LabelNames(ctx, time.Now().Add(-1*c.lookbackInterval), time.Now())
5353
return names, err
5454
}
55-
labelNames, _, err := c.prometheusClient.Series(ctx, []string{name}, startTime, endTime)
55+
labelNames, _, err := c.prometheusClient.Series(ctx, []string{name}, time.Now().Add(-1*c.lookbackInterval), time.Now())
5656
if err != nil {
5757
return nil, err
5858
}
@@ -70,16 +70,19 @@ func (c *compatibleHTTPClient) LabelNames(ctx context.Context, name string,
7070
return result, nil
7171
}
7272

73-
func (c *compatibleHTTPClient) LabelValues(ctx context.Context, label string,
74-
startTime time.Time, endTime time.Time) ([]model.LabelValue, error) {
75-
values, _, err := c.prometheusClient.LabelValues(ctx, label, startTime, endTime)
73+
func (c *compatibleHTTPClient) LabelValues(ctx context.Context, label string) ([]model.LabelValue, error) {
74+
values, _, err := c.prometheusClient.LabelValues(ctx, label, time.Now().Add(-1*c.lookbackInterval), time.Now())
7675
return values, err
7776
}
7877

7978
func (c *compatibleHTTPClient) ChangeDataSource(_ string) error {
8079
return fmt.Errorf("method not supported")
8180
}
8281

82+
func (c *compatibleHTTPClient) SetLookbackInterval(interval time.Duration) {
83+
c.lookbackInterval = interval
84+
}
85+
8386
func (c *compatibleHTTPClient) GetURL() string {
8487
return ""
8588
}

prometheus/empty.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,22 @@ func (c *emptyHTTPClient) AllMetricMetadata(_ context.Context) (map[string][]v1.
3434
return make(map[string][]v1.Metadata), nil
3535
}
3636

37-
func (c *emptyHTTPClient) LabelNames(_ context.Context, _ string, _ time.Time, _ time.Time) ([]string, error) {
37+
func (c *emptyHTTPClient) LabelNames(_ context.Context, _ string) ([]string, error) {
3838
return []string{}, nil
3939
}
4040

41-
func (c *emptyHTTPClient) LabelValues(_ context.Context, _ string, _ time.Time, _ time.Time) ([]model.LabelValue, error) {
41+
func (c *emptyHTTPClient) LabelValues(_ context.Context, _ string) ([]model.LabelValue, error) {
4242
return []model.LabelValue{}, nil
4343
}
4444

4545
func (c *emptyHTTPClient) ChangeDataSource(_ string) error {
4646
return fmt.Errorf("method not supported")
4747
}
4848

49+
func (c *emptyHTTPClient) SetLookbackInterval(_ time.Duration) {
50+
51+
}
52+
4953
func (c *emptyHTTPClient) GetURL() string {
5054
return ""
5155
}

prometheus/metadata_service.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,14 @@ type MetadataService interface {
9292
AllMetricMetadata(ctx context.Context) (map[string][]v1.Metadata, error)
9393
// LabelNames returns all the unique label names present in the block in sorted order.
9494
// If a metric is provided, then it will return all unique label names linked to the metric during a predefined period of time
95-
LabelNames(ctx context.Context, metricName string, startTime time.Time, endTime time.Time) ([]string, error)
95+
LabelNames(ctx context.Context, metricName string) ([]string, error)
9696
// LabelValues performs a query for the values of the given label.
97-
LabelValues(ctx context.Context, label string, startTime time.Time, endTime time.Time) ([]model.LabelValue, error)
97+
LabelValues(ctx context.Context, label string) ([]model.LabelValue, error)
9898
// ChangeDataSource is used if the prometheusURL is changing.
9999
// The client should re init its own parameter accordingly if necessary
100100
ChangeDataSource(prometheusURL string) error
101+
// SetLookbackInterval is a method to use to change the interval that then will be used to retrieve data such as label and metrics from prometheus.
102+
SetLookbackInterval(interval time.Duration)
101103
// GetURL is returning the url used to contact the prometheus server
102104
// In case the instance is used directly in Prometheus, it should be the externalURL
103105
GetURL() string
@@ -108,15 +110,17 @@ type MetadataService interface {
108110
// because it will manage which sub instance of the Client to use (like a factory).
109111
type httpClient struct {
110112
MetadataService
111-
requestTimeout time.Duration
112-
mutex sync.RWMutex
113-
subClient MetadataService
114-
url string
113+
requestTimeout time.Duration
114+
mutex sync.RWMutex
115+
subClient MetadataService
116+
url string
117+
lookbackInterval time.Duration
115118
}
116119

117-
func NewClient(prometheusURL string) (MetadataService, error) {
120+
func NewClient(prometheusURL string, lookbackInterval time.Duration) (MetadataService, error) {
118121
c := &httpClient{
119-
requestTimeout: 30,
122+
requestTimeout: 30,
123+
lookbackInterval: lookbackInterval,
120124
}
121125
if err := c.ChangeDataSource(prometheusURL); err != nil {
122126
return nil, err
@@ -136,18 +140,16 @@ func (c *httpClient) AllMetricMetadata(ctx context.Context) (map[string][]v1.Met
136140
return c.subClient.AllMetricMetadata(ctx)
137141
}
138142

139-
func (c *httpClient) LabelNames(ctx context.Context, name string,
140-
startTime time.Time, endTime time.Time) ([]string, error) {
143+
func (c *httpClient) LabelNames(ctx context.Context, name string) ([]string, error) {
141144
c.mutex.RLock()
142145
defer c.mutex.RUnlock()
143-
return c.subClient.LabelNames(ctx, name, startTime, endTime)
146+
return c.subClient.LabelNames(ctx, name)
144147
}
145148

146-
func (c *httpClient) LabelValues(ctx context.Context, label string,
147-
startTime time.Time, endTime time.Time) ([]model.LabelValue, error) {
149+
func (c *httpClient) LabelValues(ctx context.Context, label string) ([]model.LabelValue, error) {
148150
c.mutex.RLock()
149151
defer c.mutex.RUnlock()
150-
return c.subClient.LabelValues(ctx, label, startTime, endTime)
152+
return c.subClient.LabelValues(ctx, label)
151153
}
152154

153155
func (c *httpClient) GetURL() string {
@@ -156,6 +158,13 @@ func (c *httpClient) GetURL() string {
156158
return c.url
157159
}
158160

161+
func (c *httpClient) SetLookbackInterval(interval time.Duration) {
162+
c.mutex.Lock()
163+
defer c.mutex.Unlock()
164+
c.lookbackInterval = interval
165+
c.subClient.SetLookbackInterval(interval)
166+
}
167+
159168
func (c *httpClient) ChangeDataSource(prometheusURL string) error {
160169
c.mutex.Lock()
161170
defer c.mutex.Unlock()
@@ -192,10 +201,12 @@ func (c *httpClient) ChangeDataSource(prometheusURL string) error {
192201
if isCompatible {
193202
c.subClient = &compatibleHTTPClient{
194203
prometheusClient: v1.NewAPI(prometheusHTTPClient),
204+
lookbackInterval: c.lookbackInterval,
195205
}
196206
} else {
197207
c.subClient = &notCompatibleHTTPClient{
198208
prometheusClient: v1.NewAPI(prometheusHTTPClient),
209+
lookbackInterval: c.lookbackInterval,
199210
}
200211
}
201212

0 commit comments

Comments
 (0)