1package data
2
3import (
4	"encoding/json"
5	"fmt"
6)
7
8// FrameMeta matches:
9// https://github.com/grafana/grafana/blob/master/packages/grafana-data/src/types/data.ts#L11
10// NOTE -- in javascript this can accept any `[key: string]: any;` however
11// this interface only exposes the values we want to be exposed
12type FrameMeta struct {
13	// Type asserts that the frame matches a known type structure
14	Type FrameType `json:"type,omitempty"`
15
16	// Path is a browsable path on the datasource.
17	Path string `json:"path,omitempty"`
18
19	// PathSeparator defines the separator pattern to decode a hiearchy. The default separator is '/'.
20	PathSeparator string `json:"pathSeparator,omitempty"`
21
22	// Custom datasource specific values.
23	Custom interface{} `json:"custom,omitempty"`
24
25	// Stats is an array of query result statistics.
26	Stats []QueryStat `json:"stats,omitempty"`
27
28	// Notices provide additional information about the data in the Frame that
29	// Grafana can display to the user in the user interface.
30	Notices []Notice `json:"notices,omitempty"`
31
32	// Channel is the path to a stream in grafana live that has real-time updates for this data.
33	Channel string `json:"channel,omitempty"`
34
35	// PreferredVisualization is currently used to show results in Explore only in preferred visualisation option.
36	PreferredVisualization VisType `json:"preferredVisualisationType,omitempty"`
37
38	// ExecutedQueryString is the raw query sent to the underlying system. All macros and templating
39	// have been applied.  When metadata contains this value, it will be shown in the query inspector.
40	ExecutedQueryString string `json:"executedQueryString,omitempty"`
41}
42
43// Should be kept in sync with grafana/packages/grafana-data/src/types/data.ts#PreferredVisualisationType
44const (
45	// VisTypeGraph indicates the response should be visualized using a graph.
46	VisTypeGraph VisType = "graph"
47
48	// VisTypeTable indicates the response should be visualized using a table.
49	VisTypeTable = "table"
50
51	// VisTypeLogs indicates the response should be visualized using a logs visualization.
52	VisTypeLogs = "logs"
53
54	// VisTypeTrace indicates the response should be visualized using a trace view visualization.
55	VisTypeTrace = "trace"
56
57	// VisTypeNodeGraph indicates the response should be visualized using a node graph visualization.
58	VisTypeNodeGraph = "nodeGraph"
59)
60
61// VisType is used to indicate how the data should be visualized in explore.
62type VisType string
63
64// FrameMetaFromJSON creates a QueryResultMeta from a json string
65func FrameMetaFromJSON(jsonStr string) (*FrameMeta, error) {
66	var m FrameMeta
67	err := json.Unmarshal([]byte(jsonStr), &m)
68	if err != nil {
69		return nil, err
70	}
71	return &m, nil
72}
73
74// AppendNotices adds notices to Frame f's metadata (Frame.Meta.Notices).
75// If f has no metadata, this method will initialize it before adding notices.
76func (f *Frame) AppendNotices(notices ...Notice) {
77	if f.Meta == nil {
78		f.Meta = &FrameMeta{}
79	}
80	f.Meta.Notices = append(f.Meta.Notices, notices...)
81}
82
83// QueryStat is used for storing arbitrary statistics metadata related to a query and its result, e.g. total request time, data processing time.
84// The embedded FieldConfig's display name must be set.
85// It corresponds to the QueryResultMetaStat on the frontend (https://github.com/grafana/grafana/blob/master/packages/grafana-data/src/types/data.ts#L53).
86type QueryStat struct {
87	FieldConfig
88
89	Value float64 `json:"value"`
90}
91
92// Notice provides a structure for presenting notifications in Grafana's user interface.
93type Notice struct {
94	// Severity is the severity level of the notice: info, warning, or error.
95	Severity NoticeSeverity `json:"severity,omitempty"`
96
97	// Text is freeform descriptive text for the notice.
98	Text string `json:"text"`
99
100	// Link is an optional link for display in the user interface and can be an
101	// absolute URL or a path relative to Grafana's root url.
102	Link string `json:"link,omitempty"`
103
104	// Inspect is an optional suggestion for which tab to display in the panel inspector
105	// in Grafana's User interface. Can be meta, error, data, or stats.
106	Inspect InspectType `json:"inspect,omitempty"`
107}
108
109const (
110	noticeSeverityInfoString    = "info"
111	noticeSeverityWarningString = "warning"
112	noticeSeverityErrorString   = "error"
113)
114
115// NoticeSeverity is a type for the Severity property of a Notice.
116type NoticeSeverity int
117
118const (
119	// NoticeSeverityInfo is informational severity.
120	NoticeSeverityInfo NoticeSeverity = iota
121
122	// NoticeSeverityWarning is warning severity.
123	NoticeSeverityWarning
124
125	// NoticeSeverityError is error severity.
126	NoticeSeverityError
127)
128
129func (n NoticeSeverity) String() string {
130	switch n {
131	case NoticeSeverityInfo:
132		return noticeSeverityInfoString
133	case NoticeSeverityWarning:
134		return noticeSeverityWarningString
135	case NoticeSeverityError:
136		return noticeSeverityErrorString
137	default:
138		return ""
139	}
140}
141
142// MarshalJSON implements the json.Marshaler interface.
143func (n NoticeSeverity) MarshalJSON() ([]byte, error) {
144	return json.Marshal(n.String())
145}
146
147// UnmarshalJSON implements the json.Unmarshaler interface.
148func (n *NoticeSeverity) UnmarshalJSON(b []byte) error {
149	var s string
150	err := json.Unmarshal(b, &s)
151	if err != nil {
152		return err
153	}
154	switch s {
155	case noticeSeverityInfoString:
156		*n = NoticeSeverityInfo
157	case noticeSeverityWarningString:
158		*n = NoticeSeverityWarning
159	case noticeSeverityErrorString:
160		*n = NoticeSeverityError
161	default:
162		return fmt.Errorf("unrecognized notice severity %v", s)
163	}
164	return nil
165}
166
167// InspectType is a type for the Inspect property of a Notice.
168type InspectType int
169
170const (
171	// InspectTypeNone is no suggestion for a tab of the panel editor in Grafana's user interface.
172	InspectTypeNone InspectType = iota
173
174	// InspectTypeMeta suggests the "meta" tab of the panel editor in Grafana's user interface.
175	InspectTypeMeta
176
177	// InspectTypeError suggests the "error" tab of the panel editor in Grafana's user interface.
178	InspectTypeError
179
180	// InspectTypeData suggests the "data" tab of the panel editor in Grafana's user interface.
181	InspectTypeData
182
183	// InspectTypeStats suggests the "stats" tab of the panel editor in Grafana's user interface.
184	InspectTypeStats
185)
186
187func (n InspectType) String() string {
188	switch n {
189	case InspectTypeNone:
190		return "" // default, omitempty when encoded to json.
191	case InspectTypeMeta:
192		return "meta"
193	case InspectTypeError:
194		return "error"
195	case InspectTypeData:
196		return "data"
197	case InspectTypeStats:
198		return "stats"
199	}
200	return ""
201}
202