grafana/pkg
owensmallwood cfdea1ee30
PublicDashboards: Frontend routing for public dashboards (#48834)
* add isPublic to dashboard

* refactor routes to use route group and add placeholder method for sharing apii

* add sharing pane and utils for public dashboard config to sharing modal

* Sharing modal now persists data through the api

* moves ShareDashboard endpoint to new file and starts adding tests

* generates mocks. Adds tests for public dashboard feature flag

* Adds ability to pass in array of features to enable for the test

* test to update public flag on dashboard WIP

* Adds mock for SaveDashboardSharingConfig

* Fixes tests. Had to use FakeDashboardService

* Adds React tests for public dashboards toggle

* removes semicolons

* refactors SharePublic component to use hooks

* rename from `share publicly` to `public dashboard config`

* checkpoint. debugging tests. need to verify name changes

* checkpoint. test bugs fixed. need to finish returning proper response codes

* finish renaming. fix test

* Update pkg/api/api.go

Co-authored-by: Torkel Ödegaard <torkel@grafana.com>

* update backend url

* rename internal objects and commands. fix configuration modal labels

* add endpoint for retrieving public dashboard configuration and populate the frontend state from it

* add test for dashboardCanBePublic

* adds backend routes

* copy DashboardPage component into component for public dashboards. WIP

* adds react routes, and doesnt render main nav bar when viewing a public route

* removes extra react route from testing

* updates component name

* Wrap the original dashboard component so we can pass props relevant to public dashboards, turn kiosk mode on/off, etc

* Wraps DashboardPage in PublicDashboardPage component. DashboardPage gets rendered in kiosk mode when public prop is passed.

* removes commented out code from exploratory work

* Makes public dashboard routes require no auth

* extracts helper to own util file to check if were viewing a public page

* Hides panel dropdown when its being viewed publicly

* formatting

* use function from utils file for determining if publicly viewed. If public, hides app notifications, searchwrapper, and commandpalette.

* adds unit tests for util function used to see if page is being viewed publicly

* cant added annotations to panel when being publicly viewed

* removes useless comment

* hides backend and frontend pubdash routes behind feature flag

* consider feature flag when checking url path to see if on public dashboard

* renames function

* still render app notifications when in public view

* Extract pubdash route logic into own file

* fixes failing tests

* Determines path using location locationUtils. This covers the case when grafana is being hosted on a subpath. Updates tests.

* renames pubdash web route to be more understandable

* rename route

* fixes failing test

* fixes failing test. Needed to update pubdash urls

* sets flag on grafana boot config for if viewing public dashboard. Removes hacky check that looks at the url

* fixes failing tests. Uses config to determine if viewing public dashboard

* renders the blue panel timeInfo on public dashboard panel

* Extracts conditional logic for rendering components out into their own functions

* removes publicDashboardView check, and uses dashboard meta instead

* the timeInfo is always displayed on the panel

* After fetch of public dashboard dto, the meta isPublic flag gets set and used to determine if viewing public dashboard for child components. Fixes tests for PanelHeader.

* Fixes failing test. Needed to add isPublic flag to dashboard meta.

Co-authored-by: Jeff Levin <jeff@levinology.com>
Co-authored-by: Torkel Ödegaard <torkel@grafana.com>
2022-06-02 14:57:55 -06:00
..
api PublicDashboards: Frontend routing for public dashboards (#48834) 2022-06-02 14:57:55 -06:00
build Add nolint to two lines in fs.go (#49357) 2022-05-21 12:14:58 +02:00
bus Chore: Remove bus.Bus field (#47695) 2022-04-13 15:24:13 +02:00
cmd schema: Generate Go and Typescript from Thema coremodels (#49193) 2022-05-27 03:21:37 +02:00
codegen schema: Generate Go and Typescript from Thema coremodels (#49193) 2022-05-27 03:21:37 +02:00
components ServiceAccounts: Add identifiable token prefix to service account tokens (#49011) 2022-05-23 13:14:38 +02:00
coremodel/dashboard schema: Use latest cuetsy to fix union generation (#50013) 2022-06-01 13:14:55 -04:00
cuectx use forward slashes in cue ctx (#49440) 2022-05-23 22:00:30 +02:00
events Add event after datasource create (#38467) 2021-08-26 08:50:05 -05:00
expr SSE/Alerting: Support prom instant vector responses (#44865) 2022-05-23 10:08:14 -04:00
extensions Update cron library for ldap sync (#47983) 2022-04-26 14:14:48 +02:00
framework/coremodel schema: Generate Go and Typescript from Thema coremodels (#49193) 2022-05-27 03:21:37 +02:00
ifaces/gcsifaces GCS image uploader: Add tests (#28521) 2020-10-26 20:35:12 +01:00
infra Tracing: Deprecate opentracing (#50058) 2022-06-02 14:13:00 +02:00
login Azure OAuth: silent fail on getting groups (#49909) 2022-06-01 17:10:47 +02:00
middleware PublicDashboards: Frontend routing for public dashboards (#48834) 2022-06-02 14:57:55 -06:00
mocks/mock_gcsifaces Plugins: Requests validator (#30445) 2021-02-03 20:47:45 +01:00
models PublicDashboards: Frontend routing for public dashboards (#48834) 2022-06-02 14:57:55 -06:00
plugins Plugins: Support headers field for check health (#49930) 2022-05-31 17:58:06 +02:00
registry Chore: Add Usage stats providers registry (#48357) 2022-04-28 13:06:49 +04:00
schema schema: Finish converting dashboard schema datasource references to objects (#47806) 2022-04-15 19:41:07 +02:00
server API: Migrate CSRF to service and support additional options (#48120) 2022-06-02 15:52:30 +02:00
services Search (SQL): support dashboardUID query parameter (#50121) 2022-06-02 12:56:01 -07:00
setting Settings: Sunset non-duration based login lifetime config (#49944) 2022-06-01 12:29:15 +02:00
tests RBAC: Make RBAC action names more consistent (#49730) 2022-06-02 13:14:48 +01:00
tsdb loki: add cookie-handling functionality (#49978) 2022-06-02 11:52:27 +02:00
util Prometheus: Fix sort issue in wide frames (#49660) 2022-05-25 23:32:55 -04:00
web pkg/web: remove dependency injection (#49123) 2022-05-24 15:35:08 -04:00
README.md Contribute: Ongoing refactoring of context.Context everywhere (#36363) 2021-07-02 17:07:21 +02:00
ruleguard.rules.go Chore: update all +build statements (#38782) 2021-09-01 17:38:56 +03:00

Backend

This directory contains the code for the Grafana backend. This document gives an overview of the directory structure, and ongoing refactorings.

For more information on developing for the backend:

Central folders of Grafana's backend

folder description
/pkg/api HTTP handlers and routing. Almost all handler funcs are global which is something we would like to improve in the future. Handlers should be associated with a struct that refers to all dependencies.
/pkg/cmd The binaries that we build: grafana-server and grafana-cli.
/pkg/components A mix of third-party packages and packages we have implemented ourselves. Includes our packages that have out-grown the util package and don't naturally belong somewhere else.
/pkg/infra Packages in infra should be packages that are used in multiple places in Grafana without knowing anything about the Grafana domain.
/pkg/services Packages in services are responsible for persisting domain objects and manage the relationship between domain objects. Services should communicate with each other using DI when possible. Most of Grafana's codebase still relies on global state for this. Any new features going forward should use DI.
/pkg/tsdb All backend implementations of the data sources in Grafana. Used by both Grafana's frontend and alerting.
/pkg/util Small helper functions that are used in multiple parts of the codebase. Many functions are placed directly in the util folders which is something we want to avoid. Its better to give the util function a more descriptive package name. Ex errutil.

Central components of Grafana's backend

package description
/pkg/bus The bus is described in more details under Communication
/pkg/models This is where we keep our domain model. This package should not depend on any package outside standard library. It does contain some references within Grafana but that is something we should avoid going forward.
/pkg/registry Package for managing services.
/pkg/services/alerting Grafana's alerting services. The alerting engine runs in a separate goroutine and shouldn't depend on anything else within Grafana.
/pkg/services/sqlstore Currently where the database logic resides.
/pkg/setting Anything related to Grafana global configuration should be dealt with in this package.

Dependency management

Refer to UPGRADING_DEPENDENCIES.md.

Ongoing refactoring

These issues are not something we want to address all at once but something we will improve incrementally. Since Grafana is released at a regular schedule the preferred approach is to do this in batches. Not only is it easier to review, but it also reduces the risk of conflicts when cherry-picking fixes from main to release branches. Please try to submit changes that span multiple locations at the end of the release cycle. We prefer to wait until the end because we make fewer patch releases at the end of the release cycle, so there are fewer opportunities for complications.

Global state

Global state makes testing and debugging software harder and it's something we want to avoid when possible. Unfortunately, there is quite a lot of global state in Grafana.

We want to migrate away from this by using the inject package to wire up all dependencies either in pkg/cmd/grafana-server/main.go or self-registering using registry.RegisterService ex https://github.com/grafana/grafana/blob/main/pkg/services/cleanup/cleanup.go#L25.

Limit the use of the init() function

Only use the init() function to register services/implementations.

Settings refactoring

The plan is to move all settings to from package level vars in settings package to the setting.Cfg struct. To access the settings, services and components can inject this setting.Cfg struct:

Cfg struct Injection example

Reduce the use of GoConvey

We want to migrate away from using GoConvey. Instead, we want to use stdlib testing, because it's the most common approach in the Go community and we think it will be easier for new contributors. Read more about how we want to write tests in the style guide.

Refactor SqlStore

The sqlstore handlers all use a global xorm engine variable. Refactor them to use the SqlStore instance.

Avoid global HTTP handler functions

Refactor HTTP handlers so that the handler methods are on the HttpServer instance or a more detailed handler struct. E.g (AuthHandler). This ensures they get access to HttpServer service dependencies (and Cfg object) and can avoid global state.

Date comparison

Store newly introduced date columns in the database as epochs if they require date comparison. This permits a unified approach for comparing dates against all the supported databases instead of handling dates differently for each database. Also, by comparing epochs, we no longer need error pruning transformations to and from other time zones.

Avoid use of the simplejson package

Use of the simplejson package (pkg/components/simplejson) in place of types (Go structs) results in code that is difficult to maintain. Instead, create types for objects and use the Go standard library's encoding/json package.

Provisionable*

All new features that require state should be possible to configure using config files. For example:

Today its only possible to provision data sources and dashboards but this is something we want to support all over Grafana.

Use context.Context "everywhere"

The package context should be used and propagated through all the layers of the code. For example the context.Context of an incoming API request should be propagated to any other layers being used such as the bus, service and database layers. Utility functions/methods normally doesn't need context.Context To follow best practices, any function/method that receives a context.Context argument should receive it as its first argument.

To be able to solve certain problems and/or implement and support certain features making sure that context.Context is passed down through all layers of the code is vital. Being able to provide contextual information for the full life-cycle of an API request allows us to use contextual logging, provide contextual information about the authenticated user, create multiple spans for a distributed trace of service calls and database queries etc.

Code should use context.TODO when it's unclear which Context to use or it is not yet available (because the surrounding function has not yet been extended to accept a context.Context argument).

More details in Services, Communication and Database.

Original design doc.