Analytics: Instrument Azure Application Insights (#38553)

* add backend

* read config and pass to backend

* update config docs

* change var name

* use connection string instead of instrumentation key

* add config for endpoint url. update docs

* update default ini

* add spaces

* remove space

* Update docs/sources/administration/configuration.md

Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com>

* Update conf/defaults.ini

Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com>

* Update conf/defaults.ini

Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com>

Co-authored-by: achatterjee-grafana <70489351+achatterjee-grafana@users.noreply.github.com>
pull/39239/head
Erik Sundell 4 years ago committed by GitHub
parent 6005e6572d
commit 9d3f4f5983
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      conf/defaults.ini
  2. 7
      docs/sources/administration/configuration.md
  3. 2
      packages/grafana-runtime/src/config.ts
  4. 66
      pkg/api/frontendsettings.go
  5. 10
      pkg/setting/setting.go
  6. 10
      public/app/app.ts
  7. 48
      public/app/core/services/echo/backends/analytics/ApplicationInsightsBackend.ts

@ -208,6 +208,12 @@ rudderstack_write_key =
# Rudderstack data plane url, enabled only if rudderstack_write_key is also set # Rudderstack data plane url, enabled only if rudderstack_write_key is also set
rudderstack_data_plane_url = rudderstack_data_plane_url =
# Application Insights connection string. Specify an URL string to enable this feature.
application_insights_connection_string =
# Optional. Specifies an Application Insights endpoint URL where the endpoint string is wrapped in backticks ``.
application_insights_endpoint_url =
#################################### Security ############################ #################################### Security ############################
[security] [security]
# disable creation of admin user on first start of grafana # disable creation of admin user on first start of grafana

@ -468,6 +468,13 @@ Analytics ID here. By default this feature is disabled.
Google Tag Manager ID, only enabled if you enter an ID here. Google Tag Manager ID, only enabled if you enter an ID here.
### application_insights_connection_string
If you want to track Grafana usage via Azure Application Insights, then specify _your_ Application Insights connection string. Since the connection string contains semicolons, you need to wrap it in backticks (`). By default, tracking usage is disabled.
### application_insights_endpoint_url
Optionally, use this option to override the default endpoint address for Application Insights data collecting. For details, refer to the [Azure documentation](https://docs.microsoft.com/en-us/azure/azure-monitor/app/custom-endpoints?tabs=js).
<hr /> <hr />
## [security] ## [security]

@ -94,6 +94,8 @@ export class GrafanaBootConfig implements GrafanaConfig {
}; };
geomapDefaultBaseLayerConfig?: MapLayerOptions; geomapDefaultBaseLayerConfig?: MapLayerOptions;
geomapDisableCustomBaseLayer?: boolean; geomapDisableCustomBaseLayer?: boolean;
applicationInsightsConnectionString?: string;
applicationInsightsEndpointUrl?: string;
constructor(options: GrafanaBootConfig) { constructor(options: GrafanaBootConfig) {
const mode = options.bootData.user.lightTheme ? 'light' : 'dark'; const mode = options.bootData.user.lightTheme ? 'light' : 'dark';

@ -197,38 +197,40 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
} }
jsonObj := map[string]interface{}{ jsonObj := map[string]interface{}{
"defaultDatasource": defaultDS, "defaultDatasource": defaultDS,
"datasources": dataSources, "datasources": dataSources,
"minRefreshInterval": setting.MinRefreshInterval, "minRefreshInterval": setting.MinRefreshInterval,
"panels": panels, "panels": panels,
"appUrl": hs.Cfg.AppURL, "appUrl": hs.Cfg.AppURL,
"appSubUrl": hs.Cfg.AppSubURL, "appSubUrl": hs.Cfg.AppSubURL,
"allowOrgCreate": (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin, "allowOrgCreate": (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin,
"authProxyEnabled": setting.AuthProxyEnabled, "authProxyEnabled": setting.AuthProxyEnabled,
"ldapEnabled": hs.Cfg.LDAPEnabled, "ldapEnabled": hs.Cfg.LDAPEnabled,
"alertingEnabled": setting.AlertingEnabled, "alertingEnabled": setting.AlertingEnabled,
"alertingErrorOrTimeout": setting.AlertingErrorOrTimeout, "alertingErrorOrTimeout": setting.AlertingErrorOrTimeout,
"alertingNoDataOrNullValues": setting.AlertingNoDataOrNullValues, "alertingNoDataOrNullValues": setting.AlertingNoDataOrNullValues,
"alertingMinInterval": setting.AlertingMinInterval, "alertingMinInterval": setting.AlertingMinInterval,
"liveEnabled": hs.Cfg.LiveMaxConnections != 0, "liveEnabled": hs.Cfg.LiveMaxConnections != 0,
"autoAssignOrg": setting.AutoAssignOrg, "autoAssignOrg": setting.AutoAssignOrg,
"verifyEmailEnabled": setting.VerifyEmailEnabled, "verifyEmailEnabled": setting.VerifyEmailEnabled,
"sigV4AuthEnabled": setting.SigV4AuthEnabled, "sigV4AuthEnabled": setting.SigV4AuthEnabled,
"exploreEnabled": setting.ExploreEnabled, "exploreEnabled": setting.ExploreEnabled,
"googleAnalyticsId": setting.GoogleAnalyticsId, "googleAnalyticsId": setting.GoogleAnalyticsId,
"rudderstackWriteKey": setting.RudderstackWriteKey, "rudderstackWriteKey": setting.RudderstackWriteKey,
"rudderstackDataPlaneUrl": setting.RudderstackDataPlaneUrl, "rudderstackDataPlaneUrl": setting.RudderstackDataPlaneUrl,
"disableLoginForm": setting.DisableLoginForm, "applicationInsightsConnectionString": hs.Cfg.ApplicationInsightsConnectionString,
"disableUserSignUp": !setting.AllowUserSignUp, "applicationInsightsEndpointUrl": hs.Cfg.ApplicationInsightsEndpointUrl,
"loginHint": setting.LoginHint, "disableLoginForm": setting.DisableLoginForm,
"passwordHint": setting.PasswordHint, "disableUserSignUp": !setting.AllowUserSignUp,
"externalUserMngInfo": setting.ExternalUserMngInfo, "loginHint": setting.LoginHint,
"externalUserMngLinkUrl": setting.ExternalUserMngLinkUrl, "passwordHint": setting.PasswordHint,
"externalUserMngLinkName": setting.ExternalUserMngLinkName, "externalUserMngInfo": setting.ExternalUserMngInfo,
"viewersCanEdit": setting.ViewersCanEdit, "externalUserMngLinkUrl": setting.ExternalUserMngLinkUrl,
"editorsCanAdmin": hs.Cfg.EditorsCanAdmin, "externalUserMngLinkName": setting.ExternalUserMngLinkName,
"disableSanitizeHtml": hs.Cfg.DisableSanitizeHtml, "viewersCanEdit": setting.ViewersCanEdit,
"pluginsToPreload": pluginsToPreload, "editorsCanAdmin": hs.Cfg.EditorsCanAdmin,
"disableSanitizeHtml": hs.Cfg.DisableSanitizeHtml,
"pluginsToPreload": pluginsToPreload,
"buildInfo": map[string]interface{}{ "buildInfo": map[string]interface{}{
"hideVersion": hideVersion, "hideVersion": hideVersion,
"version": version, "version": version,

@ -369,9 +369,11 @@ type Cfg struct {
Env string Env string
// Analytics // Analytics
CheckForUpdates bool CheckForUpdates bool
ReportingDistributor string ReportingDistributor string
ReportingEnabled bool ReportingEnabled bool
ApplicationInsightsConnectionString string
ApplicationInsightsEndpointUrl string
// LDAP // LDAP
LDAPEnabled bool LDAPEnabled bool
@ -908,6 +910,8 @@ func (cfg *Cfg) Load(args CommandLineArgs) error {
if len(cfg.ReportingDistributor) >= 100 { if len(cfg.ReportingDistributor) >= 100 {
cfg.ReportingDistributor = cfg.ReportingDistributor[:100] cfg.ReportingDistributor = cfg.ReportingDistributor[:100]
} }
cfg.ApplicationInsightsConnectionString = analytics.Key("application_insights_connection_string").String()
cfg.ApplicationInsightsEndpointUrl = analytics.Key("application_insights_endpoint_url").String()
if err := readAlertingSettings(iniFile); err != nil { if err := readAlertingSettings(iniFile); err != nil {
return err return err

@ -48,6 +48,7 @@ import { getVariablesUrlParams } from './features/variables/getAllVariableValues
import getDefaultMonacoLanguages from '../lib/monaco-languages'; import getDefaultMonacoLanguages from '../lib/monaco-languages';
import { contextSrv } from './core/services/context_srv'; import { contextSrv } from './core/services/context_srv';
import { GAEchoBackend } from './core/services/echo/backends/analytics/GABackend'; import { GAEchoBackend } from './core/services/echo/backends/analytics/GABackend';
import { ApplicationInsightsBackend } from './core/services/echo/backends/analytics/ApplicationInsightsBackend';
import { RudderstackBackend } from './core/services/echo/backends/analytics/RudderstackBackend'; import { RudderstackBackend } from './core/services/echo/backends/analytics/RudderstackBackend';
import { getAllOptionEditors } from './core/components/editors/registry'; import { getAllOptionEditors } from './core/components/editors/registry';
@ -182,6 +183,15 @@ function initEchoSrv() {
}) })
); );
} }
if (config.applicationInsightsConnectionString) {
registerEchoBackend(
new ApplicationInsightsBackend({
connectionString: config.applicationInsightsConnectionString,
endpointUrl: config.applicationInsightsEndpointUrl,
})
);
}
} }
function addClassIfNoOverlayScrollbar() { function addClassIfNoOverlayScrollbar() {

@ -0,0 +1,48 @@
import $ from 'jquery';
import { EchoBackend, EchoEventType, isInteractionEvent, isPageviewEvent, PageviewEchoEvent } from '@grafana/runtime';
export interface ApplicationInsightsBackendOptions {
connectionString: string;
endpointUrl?: string;
}
export class ApplicationInsightsBackend implements EchoBackend<PageviewEchoEvent, ApplicationInsightsBackendOptions> {
supportedEvents = [EchoEventType.Pageview];
constructor(public options: ApplicationInsightsBackendOptions) {
$.ajax({
url: 'https://js.monitor.azure.com/scripts/b/ai.2.min.js',
dataType: 'script',
cache: true,
}).done(function () {
var applicationInsightsOpts = {
config: {
connectionString: options.connectionString,
endpointUrl: options.endpointUrl,
},
};
var init = new (window as any).Microsoft.ApplicationInsights.ApplicationInsights(applicationInsightsOpts);
(window as any).applicationInsights = init.loadAppInsights();
});
}
addEvent = (e: PageviewEchoEvent) => {
if (!(window as any).applicationInsights) {
return;
}
if (isPageviewEvent(e)) {
(window as any).applicationInsights.trackPageView();
}
if (isInteractionEvent(e)) {
(window as any).applicationInsights.trackPageView({
name: e.payload.interactionName,
properties: e.payload.properties,
});
}
};
// Not using Echo buffering, addEvent above sends events to Application Insights as soon as they appear
flush = () => {};
}
Loading…
Cancel
Save