1
+ import 'symbol-observable' ;
1
2
import 'core-js' ;
2
3
import 'regenerator-runtime/runtime' ;
3
- import 'symbol-observable' ;
4
4
5
- import 'file-saver' ;
6
- import 'jquery' ;
7
5
import 'whatwg-fetch' ; // fetch polyfill needed for PhantomJs rendering
8
6
import './polyfills/old-mediaquerylist' ; // Safari < 14 does not have mql.addEventListener()
7
+ import 'file-saver' ;
8
+ import 'jquery' ;
9
9
10
10
import 'app/features/all' ;
11
+
11
12
import _ from 'lodash' ; // eslint-disable-line lodash/import-scope
12
13
13
14
import {
@@ -28,19 +29,28 @@ import {
28
29
setEchoSrv ,
29
30
setLocationSrv ,
30
31
setQueryRunnerFactory ,
32
+ setRunRequest ,
33
+ setPluginImportUtils ,
34
+ setPluginExtensionGetter ,
35
+ setAppEvents ,
36
+ type GetPluginExtensions ,
31
37
} from '@grafana/runtime' ;
32
38
import { setPanelDataErrorView } from '@grafana/runtime/src/components/PanelDataErrorView' ;
33
39
import { setPanelRenderer } from '@grafana/runtime/src/components/PanelRenderer' ;
40
+ import { setPluginPage } from '@grafana/runtime/src/components/PluginPage' ;
34
41
import { getScrollbarWidth } from '@grafana/ui' ;
35
42
import config , { Settings } from 'app/core/config' ;
36
43
import { arrayMove } from 'app/core/utils/arrayMove' ;
37
44
import { getStandardTransformers } from 'app/features/transformers/standardTransformers' ;
38
45
39
46
import getDefaultMonacoLanguages from '../lib/monaco-languages' ;
40
47
48
+ import appEvents from './core/app_events' ;
41
49
import { AppChromeService } from './core/components/AppChrome/AppChromeService' ;
42
50
import { getAllOptionEditors , getAllStandardFieldConfigs } from './core/components/OptionsUI/registry' ;
51
+ import { PluginPage } from './core/components/Page/PluginPage' ;
43
52
import { GrafanaContextType } from './core/context/GrafanaContext' ;
53
+ import { initializeI18n } from './core/internationalization' ;
44
54
import { interceptLinkClicks } from './core/navigation/patch/interceptLinkClicks' ;
45
55
import { ModalManager } from './core/services/ModalManager' ;
46
56
import { backendSrv } from './core/services/backend_srv' ;
@@ -49,18 +59,25 @@ import { Echo } from './core/services/echo/Echo';
49
59
import { reportPerformance } from './core/services/echo/EchoSrv' ;
50
60
import { PerformanceBackend } from './core/services/echo/backends/PerformanceBackend' ;
51
61
import { ApplicationInsightsBackend } from './core/services/echo/backends/analytics/ApplicationInsightsBackend' ;
52
- import { GAEchoBackend } from './core/services/echo/backends/analytics/GABackend' ;
62
+ // import { GA4EchoBackend } from './core/services/echo/backends/analytics/GA4Backend';
63
+ // import { GAEchoBackend } from './core/services/echo/backends/analytics/GABackend';
53
64
import { RudderstackBackend } from './core/services/echo/backends/analytics/RudderstackBackend' ;
54
65
import { GrafanaJavascriptAgentBackend } from './core/services/echo/backends/grafana-javascript-agent/GrafanaJavascriptAgentBackend' ;
55
- import { SentryEchoBackend } from './core/services/echo/backends/sentry/SentryBackend ' ;
56
- import { initializeI18n } from './core/internationalization ' ;
66
+ import { KeybindingSrv } from './core/services/keybindingSrv ' ;
67
+ import { startMeasure , stopMeasure } from './core/utils/metrics ' ;
57
68
import { initDevFeatures } from './dev' ;
58
69
import { getTimeSrv } from './features/dashboard/services/TimeSrv' ;
70
+ // import { initGrafanaLive } from './features/live';
59
71
import { PanelDataErrorView } from './features/panel/components/PanelDataErrorView' ;
60
72
import { PanelRenderer } from './features/panel/components/PanelRenderer' ;
61
73
import { DatasourceSrv } from './features/plugins/datasource_srv' ;
74
+ import { createPluginExtensionRegistry } from './features/plugins/extensions/createPluginExtensionRegistry' ;
75
+ import { getCoreExtensionConfigurations } from './features/plugins/extensions/getCoreExtensionConfigurations' ;
76
+ import { getPluginExtensions } from './features/plugins/extensions/getPluginExtensions' ;
77
+ import { importPanelPlugin , syncGetPanelPlugin } from './features/plugins/importPanelPlugin' ;
62
78
import { preloadPlugins } from './features/plugins/pluginPreloader' ;
63
79
import { QueryRunner } from './features/query/state/QueryRunner' ;
80
+ import { runRequest } from './features/query/state/runRequest' ;
64
81
import { initWindowRuntime } from './features/runtime/init' ;
65
82
import { variableAdapters } from './features/variables/adapters' ;
66
83
import { createAdHocVariableAdapter } from './features/variables/adhoc/adapter' ;
@@ -73,7 +90,7 @@ import { setVariableQueryRunner, VariableQueryRunner } from './features/variable
73
90
import { createQueryVariableAdapter } from './features/variables/query/adapter' ;
74
91
import { createSystemVariableAdapter } from './features/variables/system/adapter' ;
75
92
import { createTextBoxVariableAdapter } from './features/variables/textbox/adapter' ;
76
- import { ConfiguredStore , configureStore } from './store/configureStore' ;
93
+ import { configureStore } from './store/configureStore' ;
77
94
78
95
// add move to lodash for backward compatabilty with plugins
79
96
// @ts -ignore
@@ -89,16 +106,42 @@ if (process.env.NODE_ENV === 'development') {
89
106
initDevFeatures ( ) ;
90
107
}
91
108
109
+ export declare type FNGrafanaStartupState = {
110
+ isLoading : boolean ;
111
+ isError : boolean ;
112
+ error ?: unknown ;
113
+ isIdeal : boolean ;
114
+ } ;
115
+
116
+ export const DefaultGrafanaStartupState : FNGrafanaStartupState = {
117
+ isLoading : false ,
118
+ isError : false ,
119
+ isIdeal : true ,
120
+ } ;
121
+
122
+ const dispatchFnEvent = ( info : FNGrafanaStartupState = DefaultGrafanaStartupState , ek = 'grafana-startup' ) => {
123
+ window . dispatchEvent (
124
+ new CustomEvent ( ek , {
125
+ detail : info ,
126
+ } )
127
+ ) ;
128
+ } ;
129
+
92
130
export class GrafanaApp {
93
131
context ! : GrafanaContextType ;
94
- readonly store : ConfiguredStore ;
95
-
96
- constructor ( ) {
97
- this . store = configureStore ( ) ;
98
- }
99
132
100
133
async init ( ) {
101
134
try {
135
+ dispatchFnEvent ( {
136
+ isIdeal : false ,
137
+ isLoading : true ,
138
+ isError : false ,
139
+ } ) ;
140
+ // Let iframe container know grafana has started loading
141
+ parent . postMessage ( 'GrafanaAppInit' , '*' ) ;
142
+
143
+ const initI18nPromise = initializeI18n ( config . bootData . user . language ) ;
144
+
102
145
backendSrv . setGrafanaPrefix ( true ) ;
103
146
setBackendSrv ( backendSrv ) ;
104
147
const settings : Settings = await backendSrv . get ( '/api/frontend/settings' ) ;
@@ -107,18 +150,28 @@ export class GrafanaApp {
107
150
config . datasources = settings . datasources ;
108
151
config . defaultDatasource = settings . defaultDatasource ;
109
152
110
- initializeI18n ( config . bootData . user . locale ) ;
111
-
112
153
initEchoSrv ( ) ;
154
+ // This needs to be done after the `initEchoSrv` since it is being used under the hood.
155
+ startMeasure ( 'frontend_app_init' ) ;
113
156
addClassIfNoOverlayScrollbar ( ) ;
114
157
setLocale ( config . bootData . user . locale ) ;
115
158
setWeekStart ( config . bootData . user . weekStart ) ;
116
159
setPanelRenderer ( PanelRenderer ) ;
160
+ setPluginPage ( PluginPage ) ;
117
161
setPanelDataErrorView ( PanelDataErrorView ) ;
118
162
setLocationSrv ( locationService ) ;
119
163
setTimeZoneResolver ( ( ) => config . bootData . user . timezone ) ;
164
+ // initGrafanaLive();
165
+
166
+ // Expose the app-wide eventbus
167
+ setAppEvents ( appEvents ) ;
168
+
169
+ // We must wait for translations to load because some preloaded store state requires translating
170
+ await initI18nPromise ;
171
+
120
172
// Important that extension reducers are initialized before store
121
173
addExtensionReducers ( ) ;
174
+ configureStore ( ) ;
122
175
initExtensions ( ) ;
123
176
124
177
standardEditorsRegistry . setInit ( getAllOptionEditors ) ;
@@ -139,6 +192,15 @@ export class GrafanaApp {
139
192
setQueryRunnerFactory ( ( ) => new QueryRunner ( ) ) ;
140
193
setVariableQueryRunner ( new VariableQueryRunner ( ) ) ;
141
194
195
+ // Provide runRequest implementation to packages, @grafana/scenes in particular
196
+ setRunRequest ( runRequest ) ;
197
+
198
+ // Privide plugin import utils to packages, @grafana/scenes in particular
199
+ setPluginImportUtils ( {
200
+ importPanelPlugin,
201
+ getPanelPluginFromCache : syncGetPanelPlugin ,
202
+ } ) ;
203
+
142
204
locationUtil . initialize ( {
143
205
config,
144
206
getTimeRangeForUrl : getTimeSrv ( ) . timeRangeForUrl ,
@@ -159,20 +221,52 @@ export class GrafanaApp {
159
221
modalManager . init ( ) ;
160
222
161
223
// Preload selected app plugins
162
- await preloadPlugins ( config . pluginsToPreload ) ;
224
+ const preloadResults = await preloadPlugins ( config . apps ) ;
225
+
226
+ // Create extension registry out of preloaded plugins and core extensions
227
+ const extensionRegistry = createPluginExtensionRegistry ( [
228
+ { pluginId : 'grafana' , extensionConfigs : getCoreExtensionConfigurations ( ) } ,
229
+ ...preloadResults ,
230
+ ] ) ;
231
+
232
+ // Expose the getPluginExtension function via grafana-runtime
233
+ const pluginExtensionGetter : GetPluginExtensions = ( options ) =>
234
+ getPluginExtensions ( { ...options , registry : extensionRegistry } ) ;
235
+
236
+ setPluginExtensionGetter ( pluginExtensionGetter ) ;
237
+
238
+ // initialize chrome service
239
+ const queryParams = locationService . getSearchObject ( ) ;
240
+ const chromeService = new AppChromeService ( ) ;
241
+ const keybindingsService = new KeybindingSrv ( locationService , chromeService ) ;
242
+
243
+ // Read initial kiosk mode from url at app startup
244
+ chromeService . setKioskModeFromUrl ( queryParams . kiosk ) ;
163
245
164
246
this . context = {
165
247
backend : backendSrv ,
166
248
location : locationService ,
167
- chrome : new AppChromeService ( ) ,
249
+ chrome : chromeService ,
250
+ keybindings : keybindingsService ,
168
251
config,
169
252
} ;
253
+
254
+ dispatchFnEvent ( {
255
+ isLoading : false ,
256
+ isError : false ,
257
+ isIdeal : false ,
258
+ } ) ;
170
259
} catch ( error ) {
260
+ dispatchFnEvent ( {
261
+ isLoading : false ,
262
+ isError : true ,
263
+ error,
264
+ isIdeal : false ,
265
+ } ) ;
171
266
console . error ( 'Failed to start Grafana' , error ) ;
172
-
173
- if ( window . __grafana_load_failed ) {
174
- window . __grafana_load_failed ( ) ;
175
- }
267
+ window . __grafana_load_failed ( ) ;
268
+ } finally {
269
+ stopMeasure ( 'frontend_app_init' ) ;
176
270
}
177
271
}
178
272
}
@@ -212,15 +306,6 @@ function initEchoSrv() {
212
306
registerEchoBackend ( new PerformanceBackend ( { } ) ) ;
213
307
}
214
308
215
- if ( config . sentry . enabled ) {
216
- registerEchoBackend (
217
- new SentryEchoBackend ( {
218
- ...config . sentry ,
219
- user : config . bootData . user ,
220
- buildInfo : config . buildInfo ,
221
- } )
222
- ) ;
223
- }
224
309
if ( config . grafanaJavascriptAgent . enabled ) {
225
310
registerEchoBackend (
226
311
new GrafanaJavascriptAgentBackend ( {
@@ -238,13 +323,22 @@ function initEchoSrv() {
238
323
) ;
239
324
}
240
325
241
- if ( config . googleAnalyticsId ) {
242
- registerEchoBackend (
243
- new GAEchoBackend ( {
244
- googleAnalyticsId : config . googleAnalyticsId ,
245
- } )
246
- ) ;
247
- }
326
+ // if (config.googleAnalyticsId) {
327
+ // registerEchoBackend(
328
+ // new GAEchoBackend({
329
+ // googleAnalyticsId: config.googleAnalyticsId,
330
+ // })
331
+ // );
332
+ // }
333
+
334
+ // if (config.googleAnalytics4Id) {
335
+ // registerEchoBackend(
336
+ // new GA4EchoBackend({
337
+ // googleAnalyticsId: config.googleAnalytics4Id,
338
+ // googleAnalytics4SendManualPageViews: config.googleAnalytics4SendManualPageViews,
339
+ // })
340
+ // );
341
+ // }
248
342
249
343
if ( config . rudderstackWriteKey && config . rudderstackDataPlaneUrl ) {
250
344
registerEchoBackend (
@@ -254,6 +348,7 @@ function initEchoSrv() {
254
348
user : config . bootData . user ,
255
349
sdkUrl : config . rudderstackSdkUrl ,
256
350
configUrl : config . rudderstackConfigUrl ,
351
+ buildInfo : config . buildInfo ,
257
352
} )
258
353
) ;
259
354
}
0 commit comments