-
Notifications
You must be signed in to change notification settings - Fork 629
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(prometheus): Initial step at plumbing in prometheus (#66)
Here is an example configuration for kayenta-local.yml prometheus: enabled: true endpoint: baseUrl: http://localhost:9090 accounts: - name: my-prometheus-server supportedTypes: - METRICS_STORE See the comment in PrometheusConfigurationProperties regarding configuring the scopeLabel. This still needs a PR to change the extension labels in order to propagate filters and "sumBy" fields from canaryController calls. However everything else is plumbed up. Without passing those fields through, alignment is unlikely because there is too much context to align (e.g. individual CPU cores are treated independent rather than summing into a single aggregated value)
- Loading branch information
Eric Wiseblatt
committed
Aug 22, 2017
1 parent
5561e54
commit ef52c30
Showing
21 changed files
with
1,114 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
.../main/java/com/netflix/kayenta/canary/providers/PrometheusCanaryMetricSetQueryConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* | ||
* Copyright 2017 Google, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License") | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.netflix.kayenta.canary.providers; | ||
|
||
import com.netflix.kayenta.canary.CanaryMetricSetQueryConfig; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.ToString; | ||
|
||
import javax.validation.constraints.NotNull; | ||
import java.util.List; | ||
|
||
@Builder | ||
@ToString | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
// TODO(duftler): Figure out how to move this into the kayenta-prometheus module? Doing so as-is would introduce a circular dependency. | ||
public class PrometheusCanaryMetricSetQueryConfig implements CanaryMetricSetQueryConfig { | ||
|
||
@NotNull | ||
@Getter | ||
private String metricName; | ||
|
||
@Getter | ||
private String aggregationPeriod; | ||
|
||
@Getter | ||
private String instancePattern; | ||
|
||
@Getter | ||
private List<String> labelBindings; | ||
|
||
@Getter | ||
private List<String> sumByFields; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
dependencies { | ||
compile project(":kayenta-core") | ||
|
||
// compile spinnaker.dependency('bootWeb') | ||
compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion" | ||
|
||
// compile spinnaker.dependency("korkSwagger") | ||
compile "com.netflix.spinnaker.kork:kork-swagger:$korkVersion" | ||
|
||
// compile spinnaker.dependency('lombok') | ||
compile "org.projectlombok:lombok:1.16.10" | ||
|
||
compile "com.netflix.spinnaker.orca:orca-core:$orcaVersion" | ||
} |
39 changes: 39 additions & 0 deletions
39
...prometheus/src/main/java/com/netflix/kayenta/prometheus/canary/PrometheusCanaryScope.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
* Copyright 2017 Google, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License") | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.netflix.kayenta.prometheus.canary; | ||
|
||
import com.netflix.kayenta.canary.CanaryScope; | ||
import lombok.Data; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.ToString; | ||
|
||
import javax.validation.constraints.NotNull; | ||
|
||
@Data | ||
@EqualsAndHashCode(callSuper = true) | ||
@ToString(callSuper = true) | ||
public class PrometheusCanaryScope extends CanaryScope { | ||
|
||
@NotNull | ||
private String type; | ||
|
||
@NotNull | ||
private String intervalStartTimeIso; | ||
|
||
@NotNull | ||
private String intervalEndTimeIso; | ||
} |
54 changes: 54 additions & 0 deletions
54
...eus/src/main/java/com/netflix/kayenta/prometheus/canary/PrometheusCanaryScopeFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
* Copyright 2017 Google, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License") | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.netflix.kayenta.prometheus.canary; | ||
|
||
import com.netflix.kayenta.canary.CanaryScope; | ||
import com.netflix.kayenta.canary.CanaryScopeFactory; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.time.Instant; | ||
import java.util.Map; | ||
|
||
@Component | ||
public class PrometheusCanaryScopeFactory implements CanaryScopeFactory { | ||
|
||
@Override | ||
public boolean handles(String serviceType) { | ||
return "prometheus".equals(serviceType); | ||
} | ||
|
||
@Override | ||
public CanaryScope buildCanaryScope(String scope, | ||
Instant startTimeInstant, | ||
Instant endTimeInstant, | ||
String step, | ||
Map<String, String> extendedScopeParams) { | ||
PrometheusCanaryScope prometheusCanaryScope = new PrometheusCanaryScope(); | ||
prometheusCanaryScope.setScope(scope); | ||
prometheusCanaryScope.setStart(startTimeInstant.toEpochMilli() + ""); | ||
prometheusCanaryScope.setEnd(endTimeInstant.toEpochMilli() + ""); | ||
prometheusCanaryScope.setIntervalStartTimeIso(startTimeInstant + ""); | ||
prometheusCanaryScope.setIntervalEndTimeIso(endTimeInstant + ""); | ||
prometheusCanaryScope.setStep(step); | ||
|
||
if (extendedScopeParams != null && extendedScopeParams.containsKey("type")) { | ||
prometheusCanaryScope.setType(extendedScopeParams.get("type")); | ||
} | ||
|
||
return prometheusCanaryScope; | ||
} | ||
} |
110 changes: 110 additions & 0 deletions
110
...ometheus/src/main/java/com/netflix/kayenta/prometheus/config/PrometheusConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
* Copyright 2017 Google, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License") | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.netflix.kayenta.prometheus.config; | ||
|
||
import com.netflix.kayenta.prometheus.metrics.PrometheusMetricsService; | ||
import com.netflix.kayenta.prometheus.security.PrometheusCredentials; | ||
import com.netflix.kayenta.prometheus.security.PrometheusNamedAccountCredentials; | ||
import com.netflix.kayenta.prometheus.service.PrometheusRemoteService; | ||
import com.netflix.kayenta.metrics.MetricsService; | ||
import com.netflix.kayenta.retrofit.config.RetrofitClientFactory; | ||
import com.netflix.kayenta.security.AccountCredentials; | ||
import com.netflix.kayenta.security.AccountCredentialsRepository; | ||
import com.squareup.okhttp.OkHttpClient; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.ComponentScan; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.util.CollectionUtils; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
|
||
@Configuration | ||
@EnableConfigurationProperties | ||
@ConditionalOnProperty("kayenta.prometheus.enabled") | ||
@ComponentScan({"com.netflix.kayenta.prometheus"}) | ||
@Slf4j | ||
public class PrometheusConfiguration { | ||
|
||
@Bean | ||
@ConfigurationProperties("kayenta.prometheus") | ||
PrometheusConfigurationProperties prometheusConfigurationProperties() { | ||
return new PrometheusConfigurationProperties(); | ||
} | ||
|
||
// This is following Atlas pattern, which uses a single global service. | ||
// However, I might rather have an endpoint per account or some list of services if monitoring is partitioned | ||
// across multiple prometheus servers. I dont know how to wire that up in Spring unless I were to change | ||
// the RemoteService to a facade that used an endpoint from the request (either injected or from credentials used). | ||
@Bean | ||
MetricsService prometheusMetricsService(PrometheusConfigurationProperties prometheusConfigurationProperties, | ||
AccountCredentialsRepository accountCredentialsRepository, | ||
PrometheusRemoteService prometheusRemoteService) throws IOException { | ||
PrometheusMetricsService.PrometheusMetricsServiceBuilder prometheusMetricsServiceBuilder = PrometheusMetricsService.builder(); | ||
prometheusMetricsServiceBuilder.scopeLabel(prometheusConfigurationProperties.getScopeLabel()); | ||
|
||
for (PrometheusManagedAccount prometheusManagedAccount : prometheusConfigurationProperties.getAccounts()) { | ||
String name = prometheusManagedAccount.getName(); | ||
List<AccountCredentials.Type> supportedTypes = prometheusManagedAccount.getSupportedTypes(); | ||
|
||
log.info("Registering Prometheus account {} with supported types {}.", name, supportedTypes); | ||
|
||
PrometheusCredentials prometheusCredentials = | ||
PrometheusCredentials | ||
.builder() | ||
.build(); | ||
PrometheusNamedAccountCredentials.PrometheusNamedAccountCredentialsBuilder prometheusNamedAccountCredentialsBuilder = | ||
PrometheusNamedAccountCredentials | ||
.builder() | ||
.name(name) | ||
.credentials(prometheusCredentials); | ||
|
||
if (!CollectionUtils.isEmpty(supportedTypes)) { | ||
if (supportedTypes.contains(AccountCredentials.Type.METRICS_STORE)) { | ||
prometheusNamedAccountCredentialsBuilder.prometheusRemoteService(prometheusRemoteService); | ||
} | ||
|
||
prometheusNamedAccountCredentialsBuilder.supportedTypes(supportedTypes); | ||
} | ||
|
||
PrometheusNamedAccountCredentials prometheusNamedAccountCredentials = prometheusNamedAccountCredentialsBuilder.build(); | ||
accountCredentialsRepository.save(name, prometheusNamedAccountCredentials); | ||
prometheusMetricsServiceBuilder.accountName(name); | ||
} | ||
|
||
PrometheusMetricsService prometheusMetricsService = prometheusMetricsServiceBuilder.build(); | ||
|
||
log.info("Populated PrometheusMetricsService with {} Prometheus accounts.", prometheusMetricsService.getAccountNames().size()); | ||
|
||
return prometheusMetricsService; | ||
} | ||
|
||
@Bean | ||
PrometheusRemoteService prometheusRemoteService(PrometheusResponseConverter prometheusConverter, | ||
PrometheusConfigurationProperties prometheusConfigurationProperties, | ||
RetrofitClientFactory retrofitClientFactory, | ||
OkHttpClient okHttpClient) { | ||
return retrofitClientFactory.createClient(PrometheusRemoteService.class, | ||
prometheusConverter, | ||
prometheusConfigurationProperties.getEndpoint(), | ||
okHttpClient); | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
...rc/main/java/com/netflix/kayenta/prometheus/config/PrometheusConfigurationProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
* Copyright 2017 Google, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License") | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.netflix.kayenta.prometheus.config; | ||
|
||
import com.netflix.kayenta.retrofit.config.RemoteService; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
import javax.validation.constraints.NotNull; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
// TODO(ewiseblatt): | ||
// @Data this class instead of @Getter/Setter and final the "accounts". | ||
public class PrometheusConfigurationProperties { | ||
|
||
/** | ||
* TODO(ewiseblatt): | ||
* We're saying "instance" here by default, which is built-in to Prometheus. | ||
* However, in practice this should be overriden to "host" where "host" | ||
* is injected on scrape by the prometheus.yml configuration. The install | ||
* for prometheus when using the --gce option does this, but that is the | ||
* only configuration that does at this time. | ||
* | ||
* The difference is that prometheus adds "instance" as the __address__, | ||
* which is the <host>:<port> but the <host> is typically an IP address. | ||
* Instance can be explicitly overriden as well, but should be the particular | ||
* service endpoint. | ||
* | ||
* In general, you do want the particular service endpoint in order to get | ||
* the particular service of interest. In the case of looking for node_cpu, | ||
* which is the default, then you would need to add the node_exporter service | ||
* to the request (i.e. instance is <host>:9100). Using the above "host", this | ||
* would collect *all* node_cpu from that host. However we assume that only | ||
* the node_exporter is exporting "node_cpu" so there is only one (port 9100). | ||
* | ||
* I need to clean this up. Perhaps by configuring default prometheus to use | ||
* the dns name instead of the IP in general for the __address__. Regardless, | ||
* the application scraping can determine its own "instance" value (as well | ||
* as "host") in which case the operator might need to compensate in how they | ||
* configure this scopeLabel value and query using it. | ||
*/ | ||
@Getter | ||
@Setter | ||
private String scopeLabel = "instance"; | ||
|
||
// Location of prometheus server. | ||
@NotNull | ||
@Getter | ||
@Setter | ||
private RemoteService endpoint; | ||
|
||
@Getter | ||
private List<PrometheusManagedAccount> accounts = new ArrayList<>(); | ||
} |
32 changes: 32 additions & 0 deletions
32
...metheus/src/main/java/com/netflix/kayenta/prometheus/config/PrometheusManagedAccount.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Copyright 2017 Google, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License") | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.netflix.kayenta.prometheus.config; | ||
|
||
import com.netflix.kayenta.security.AccountCredentials; | ||
import lombok.Data; | ||
|
||
import javax.validation.constraints.NotNull; | ||
import java.util.List; | ||
|
||
@Data | ||
public class PrometheusManagedAccount { | ||
|
||
@NotNull | ||
private String name; | ||
|
||
private List<AccountCredentials.Type> supportedTypes; | ||
} |
Oops, something went wrong.