-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(grafana): add grafana support (#137)
### Description This PR builds on the [previously-added Prometheus support](#134) to add Grafana support by: - adding a `grafana_params` section to the top-level `observability` parameter section - deploying a Grafana server - implementing dashboard provisioning The `grafana` module from the `ethereum-package` package was used as inspiration, but modified to simplify devX by removing support for inline dashboards and improving remote dashboard source support. Additionally, this PR implements API provisioning using the official [grizzly](https://grafana.github.io/grizzly/) tool, over the existing file-based provisioning approach to simplify the process of keeping Kurtosis Grafana in-sync with hosted Grafana. To this end, two new repositories ([`grafana-dashboards`](https://github.com/ethereum-optimism/grafana-dashboards), [`grafana-dashboards-public`](https://github.com/ethereum-optimism/grafana-dashboards-public)) have been created, with the intention of tracking extant public & private dashboards in hosted Grafana. This PR has been tested and successfully deploys a Grafana server with including all public dashboards present on our hosted Grafana instance, organized into the same folder structure: <img width="1214" alt="image" src="https://github.com/user-attachments/assets/9a007f0e-fb95-4399-9a96-8be3f33e4eba" /> Not all dashboards are yet at full parity, but a fair number of them do show data: <img width="1807" alt="image" src="https://github.com/user-attachments/assets/d1223067-9d31-4b8c-a76a-a9d7b4b4c787" /> If you want to try this out locally, add the following snippet to your params file: ```yaml optimism_package: observability: grafana_params: dashboard_sources: - github.com/ethereum-optimism/grafana-dashboards-public/resources@aa35389fc5dec4043838757e2372368c3efb0a29 ``` Remaining work: - continue converging metrics to enable additional dashboards - implement promtail/loki support to enable log-based dashboard panels - deploy any services required for certain dashboards (ie replica-healthcheck) (?) - support a subset of existing dashboards using tags/folders - automatic updates of the [`grafana-dashboards`](https://github.com/ethereum-optimism/grafana-dashboards) repository
- Loading branch information
Showing
9 changed files
with
230 additions
and
4 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
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
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,144 @@ | ||
util = import_module("../../util.star") | ||
|
||
ethereum_package_shared_utils = import_module( | ||
"github.com/ethpandaops/ethereum-package/src/shared_utils/shared_utils.star" | ||
) | ||
|
||
SERVICE_NAME = "grafana" | ||
|
||
HTTP_PORT_ID = "http" | ||
HTTP_PORT_NUMBER_UINT16 = 3000 | ||
|
||
TEMPLATES_FILEPATH = "./templates" | ||
|
||
DATASOURCE_UID = "grafanacloud-prom" | ||
DATASOURCE_CONFIG_TEMPLATE_FILEPATH = TEMPLATES_FILEPATH + "/datasource.yml.tmpl" | ||
DATASOURCE_CONFIG_REL_FILEPATH = "datasources/datasource.yml" | ||
|
||
CONFIG_DIRPATH_ON_SERVICE = "/config" | ||
|
||
USED_PORTS = { | ||
HTTP_PORT_ID: ethereum_package_shared_utils.new_port_spec( | ||
HTTP_PORT_NUMBER_UINT16, | ||
ethereum_package_shared_utils.TCP_PROTOCOL, | ||
ethereum_package_shared_utils.HTTP_APPLICATION_PROTOCOL, | ||
) | ||
} | ||
|
||
|
||
def launch_grafana( | ||
plan, | ||
prometheus_private_url, | ||
global_node_selectors, | ||
grafana_params, | ||
): | ||
datasource_config_template = read_file(DATASOURCE_CONFIG_TEMPLATE_FILEPATH) | ||
|
||
grafana_config_artifact_name = upload_grafana_config( | ||
plan, | ||
datasource_config_template, | ||
prometheus_private_url, | ||
) | ||
|
||
config = get_config( | ||
grafana_config_artifact_name, | ||
global_node_selectors, | ||
grafana_params, | ||
) | ||
|
||
service = plan.add_service(SERVICE_NAME, config) | ||
|
||
service_url = "http://{0}:{1}".format( | ||
service.ip_address, service.ports[HTTP_PORT_ID].number | ||
) | ||
|
||
provision_dashboards(plan, service_url, grafana_params.dashboard_sources) | ||
|
||
return service_url | ||
|
||
|
||
def upload_grafana_config( | ||
plan, | ||
datasource_config_template, | ||
prometheus_private_url, | ||
): | ||
datasource_data = new_datasource_config_template_data(prometheus_private_url) | ||
datasource_template_and_data = ethereum_package_shared_utils.new_template_and_data( | ||
datasource_config_template, datasource_data | ||
) | ||
|
||
template_and_data_by_rel_dest_filepath = { | ||
DATASOURCE_CONFIG_REL_FILEPATH: datasource_template_and_data, | ||
} | ||
|
||
grafana_config_artifact_name = plan.render_templates( | ||
template_and_data_by_rel_dest_filepath, name="grafana-config" | ||
) | ||
|
||
return grafana_config_artifact_name | ||
|
||
|
||
def new_datasource_config_template_data(prometheus_url): | ||
return {"PrometheusUID": DATASOURCE_UID, "PrometheusURL": prometheus_url} | ||
|
||
|
||
def get_config( | ||
grafana_config_artifact_name, | ||
node_selectors, | ||
grafana_params, | ||
): | ||
return ServiceConfig( | ||
image=grafana_params.image, | ||
ports=USED_PORTS, | ||
env_vars={ | ||
"GF_PATHS_PROVISIONING": CONFIG_DIRPATH_ON_SERVICE, | ||
"GF_AUTH_ANONYMOUS_ENABLED": "true", | ||
"GF_AUTH_ANONYMOUS_ORG_ROLE": "Admin", | ||
"GF_AUTH_ANONYMOUS_ORG_NAME": "Main Org.", | ||
# "GF_DASHBOARDS_DEFAULT_HOME_DASHBOARD_PATH": "/dashboards/default.json", | ||
}, | ||
files={ | ||
CONFIG_DIRPATH_ON_SERVICE: grafana_config_artifact_name, | ||
}, | ||
min_cpu=grafana_params.min_cpu, | ||
max_cpu=grafana_params.max_cpu, | ||
min_memory=grafana_params.min_mem, | ||
max_memory=grafana_params.max_mem, | ||
node_selectors=node_selectors, | ||
) | ||
|
||
|
||
def provision_dashboards(plan, service_url, dashboard_sources): | ||
if len(dashboard_sources) == 0: | ||
return | ||
|
||
def grr_push(dir): | ||
return 'grr push "{0}" -e --disable-reporting'.format(dir) | ||
|
||
def grr_push_dashboards(name): | ||
return [ | ||
grr_push("{0}/folders".format(name)), | ||
grr_push("{0}/dashboards".format(name)), | ||
] | ||
|
||
grr_commands = [ | ||
"grr config create-context kurtosis", | ||
] | ||
|
||
files = {} | ||
for index, dashboard_src in enumerate(dashboard_sources): | ||
dashboard_name = "dashboards-{0}".format(index) | ||
dashboard_artifact_name = plan.upload_files(dashboard_src, name=dashboard_name) | ||
|
||
files[dashboard_name] = dashboard_artifact_name | ||
grr_commands += grr_push_dashboards(dashboard_name) | ||
|
||
plan.run_sh( | ||
description="upload dashboards", | ||
image="grafana/grizzly:main-0b88d01", | ||
env_vars={ | ||
"GRAFANA_URL": service_url, | ||
}, | ||
files=files, | ||
run=util.join_cmds(grr_commands), | ||
) |
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,12 @@ | ||
apiVersion: 1 | ||
|
||
datasources: | ||
- name: Prometheus | ||
type: prometheus | ||
access: proxy | ||
orgId: 1 | ||
uid: {{ .PrometheusUID }} | ||
url: {{ .PrometheusURL }} | ||
basicAuth: false | ||
isDefault: true | ||
editable: true |
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
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
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
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
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