github.com/influxdata/influxdb/v2@v2.7.6/dashboard.go (about) 1 package influxdb 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "net/url" 8 "sort" 9 "time" 10 11 "github.com/influxdata/influxdb/v2/kit/platform" 12 "github.com/influxdata/influxdb/v2/kit/platform/errors" 13 ) 14 15 // ErrDashboardNotFound is the error msg for a missing dashboard. 16 const ErrDashboardNotFound = "dashboard not found" 17 18 // ErrCellNotFound is the error msg for a missing cell. 19 const ErrCellNotFound = "cell not found" 20 21 // ErrViewNotFound is the error msg for a missing View. 22 const ErrViewNotFound = "view not found" 23 24 // ops for dashboard service. 25 const ( 26 OpFindDashboardByID = "FindDashboardByID" 27 OpFindDashboards = "FindDashboards" 28 OpCreateDashboard = "CreateDashboard" 29 OpUpdateDashboard = "UpdateDashboard" 30 OpAddDashboardCell = "AddDashboardCell" 31 OpRemoveDashboardCell = "RemoveDashboardCell" 32 OpUpdateDashboardCell = "UpdateDashboardCell" 33 OpGetDashboardCellView = "GetDashboardCellView" 34 OpUpdateDashboardCellView = "UpdateDashboardCellView" 35 OpDeleteDashboard = "DeleteDashboard" 36 OpReplaceDashboardCells = "ReplaceDashboardCells" 37 ) 38 39 // DashboardService represents a service for managing dashboard data. 40 type DashboardService interface { 41 // FindDashboardByID returns a single dashboard by ID. 42 FindDashboardByID(ctx context.Context, id platform.ID) (*Dashboard, error) 43 44 // FindDashboards returns a list of dashboards that match filter and the total count of matching dashboards. 45 // Additional options provide pagination & sorting. 46 FindDashboards(ctx context.Context, filter DashboardFilter, opts FindOptions) ([]*Dashboard, int, error) 47 48 // CreateDashboard creates a new dashboard and sets b.ID with the new identifier. 49 CreateDashboard(ctx context.Context, b *Dashboard) error 50 51 // UpdateDashboard updates a single dashboard with changeset. 52 // Returns the new dashboard state after update. 53 UpdateDashboard(ctx context.Context, id platform.ID, upd DashboardUpdate) (*Dashboard, error) 54 55 // AddDashboardCell adds a cell to a dashboard. 56 AddDashboardCell(ctx context.Context, id platform.ID, c *Cell, opts AddDashboardCellOptions) error 57 58 // RemoveDashboardCell removes a dashboard. 59 RemoveDashboardCell(ctx context.Context, dashboardID, cellID platform.ID) error 60 61 // UpdateDashboardCell replaces the dashboard cell with the provided ID. 62 UpdateDashboardCell(ctx context.Context, dashboardID, cellID platform.ID, upd CellUpdate) (*Cell, error) 63 64 // GetDashboardCellView retrieves a dashboard cells view. 65 GetDashboardCellView(ctx context.Context, dashboardID, cellID platform.ID) (*View, error) 66 67 // UpdateDashboardCellView retrieves a dashboard cells view. 68 UpdateDashboardCellView(ctx context.Context, dashboardID, cellID platform.ID, upd ViewUpdate) (*View, error) 69 70 // DeleteDashboard removes a dashboard by ID. 71 DeleteDashboard(ctx context.Context, id platform.ID) error 72 73 // ReplaceDashboardCells replaces all cells in a dashboard 74 ReplaceDashboardCells(ctx context.Context, id platform.ID, c []*Cell) error 75 } 76 77 // Dashboard represents all visual and query data for a dashboard. 78 type Dashboard struct { 79 ID platform.ID `json:"id,omitempty"` 80 OrganizationID platform.ID `json:"orgID,omitempty"` 81 Name string `json:"name"` 82 Description string `json:"description"` 83 Cells []*Cell `json:"cells"` 84 Meta DashboardMeta `json:"meta"` 85 OwnerID *platform.ID `json:"owner,omitempty"` 86 } 87 88 // DashboardMeta contains meta information about dashboards 89 type DashboardMeta struct { 90 CreatedAt time.Time `json:"createdAt"` 91 UpdatedAt time.Time `json:"updatedAt"` 92 } 93 94 // DefaultDashboardFindOptions are the default find options for dashboards 95 var DefaultDashboardFindOptions = FindOptions{ 96 SortBy: "ID", 97 } 98 99 // SortDashboards sorts a slice of dashboards by a field. 100 func SortDashboards(opts FindOptions, ds []*Dashboard) { 101 var sorter func(i, j int) bool 102 switch opts.SortBy { 103 case "CreatedAt": 104 sorter = func(i, j int) bool { 105 return ds[j].Meta.CreatedAt.After(ds[i].Meta.CreatedAt) 106 } 107 case "UpdatedAt": 108 sorter = func(i, j int) bool { 109 return ds[j].Meta.UpdatedAt.After(ds[i].Meta.UpdatedAt) 110 } 111 case "Name": 112 sorter = func(i, j int) bool { 113 return ds[i].Name < ds[j].Name 114 } 115 default: 116 sorter = func(i, j int) bool { 117 if opts.Descending { 118 return ds[i].ID > ds[j].ID 119 } 120 return ds[i].ID < ds[j].ID 121 } 122 } 123 124 sort.Slice(ds, sorter) 125 } 126 127 // Cell holds positional information about a cell on dashboard and a reference to a cell. 128 type Cell struct { 129 ID platform.ID `json:"id,omitempty"` 130 CellProperty 131 View *View `json:"-"` 132 } 133 134 // Marshals the cell 135 func (c *Cell) MarshalJSON() ([]byte, error) { 136 type resp struct { 137 ID *platform.ID `json:"id,omitempty"` 138 Name string `json:"name,omitempty"` 139 ViewProperties json.RawMessage `json:"properties,omitempty"` 140 CellProperty 141 } 142 response := resp{ 143 CellProperty: c.CellProperty, 144 } 145 if c.ID != 0 { 146 response.ID = &c.ID 147 } 148 if c.View != nil { 149 response.Name = c.View.Name 150 rawJSON, err := MarshalViewPropertiesJSON(c.View.Properties) 151 if err != nil { 152 return nil, err 153 } 154 response.ViewProperties = rawJSON 155 } 156 return json.Marshal(response) 157 } 158 159 func (c *Cell) UnmarshalJSON(b []byte) error { 160 var newCell struct { 161 ID platform.ID `json:"id,omitempty"` 162 Name string `json:"name,omitempty"` 163 ViewProperties json.RawMessage `json:"properties,omitempty"` 164 CellProperty 165 } 166 if err := json.Unmarshal(b, &newCell); err != nil { 167 return err 168 } 169 170 c.ID = newCell.ID 171 c.CellProperty = newCell.CellProperty 172 173 if newCell.Name != "" { 174 if c.View == nil { 175 c.View = new(View) 176 } 177 c.View.Name = newCell.Name 178 } 179 180 props, err := UnmarshalViewPropertiesJSON(newCell.ViewProperties) 181 if err == nil { 182 if c.View == nil { 183 c.View = new(View) 184 } 185 c.View.Properties = props 186 } 187 188 return nil 189 } 190 191 // CellProperty contains the properties of a cell. 192 type CellProperty struct { 193 X int32 `json:"x"` 194 Y int32 `json:"y"` 195 W int32 `json:"w"` 196 H int32 `json:"h"` 197 } 198 199 // DashboardFilter is a filter for dashboards. 200 type DashboardFilter struct { 201 IDs []*platform.ID 202 OrganizationID *platform.ID 203 Organization *string 204 OwnerID *platform.ID 205 } 206 207 // QueryParams turns a dashboard filter into query params 208 // 209 // It implements PagingFilter. 210 func (f DashboardFilter) QueryParams() map[string][]string { 211 qp := url.Values{} 212 for _, id := range f.IDs { 213 if id != nil { 214 qp.Add("id", id.String()) 215 } 216 } 217 218 if f.OrganizationID != nil { 219 qp.Add("orgID", f.OrganizationID.String()) 220 } 221 222 if f.Organization != nil { 223 qp.Add("org", *f.Organization) 224 } 225 226 if f.OwnerID != nil { 227 qp.Add("owner", f.OwnerID.String()) 228 } 229 230 return qp 231 } 232 233 // DashboardUpdate is the patch structure for a dashboard. 234 type DashboardUpdate struct { 235 Name *string `json:"name"` 236 Description *string `json:"description"` 237 Cells *[]*Cell `json:"cells"` 238 } 239 240 // Apply applies an update to a dashboard. 241 func (u DashboardUpdate) Apply(d *Dashboard) error { 242 if u.Name != nil { 243 d.Name = *u.Name 244 } 245 246 if u.Description != nil { 247 d.Description = *u.Description 248 } 249 250 if u.Cells != nil { 251 d.Cells = *u.Cells 252 } 253 254 return nil 255 } 256 257 // Valid returns an error if the dashboard update is invalid. 258 func (u DashboardUpdate) Valid() *errors.Error { 259 if u.Name == nil && u.Description == nil { 260 return &errors.Error{ 261 Code: errors.EInvalid, 262 Msg: "must update at least one attribute", 263 } 264 } 265 266 return nil 267 } 268 269 // AddDashboardCellOptions are options for adding a dashboard. 270 type AddDashboardCellOptions struct { 271 View *View 272 } 273 274 // CellUpdate is the patch structure for a cell. 275 type CellUpdate struct { 276 X *int32 `json:"x"` 277 Y *int32 `json:"y"` 278 W *int32 `json:"w"` 279 H *int32 `json:"h"` 280 } 281 282 // Apply applies an update to a Cell. 283 func (u CellUpdate) Apply(c *Cell) error { 284 if u.X != nil { 285 c.X = *u.X 286 } 287 288 if u.Y != nil { 289 c.Y = *u.Y 290 } 291 292 if u.W != nil { 293 c.W = *u.W 294 } 295 296 if u.H != nil { 297 c.H = *u.H 298 } 299 300 return nil 301 } 302 303 // Valid returns an error if the cell update is invalid. 304 func (u CellUpdate) Valid() *errors.Error { 305 if u.H == nil && u.W == nil && u.Y == nil && u.X == nil { 306 return &errors.Error{ 307 Code: errors.EInvalid, 308 Msg: "must update at least one attribute", 309 } 310 } 311 312 return nil 313 } 314 315 // ViewUpdate is a struct for updating Views. 316 type ViewUpdate struct { 317 ViewContentsUpdate 318 Properties ViewProperties 319 } 320 321 // Valid validates the update struct. It expects minimal values to be set. 322 func (u ViewUpdate) Valid() *errors.Error { 323 _, ok := u.Properties.(EmptyViewProperties) 324 if u.Name == nil && ok { 325 return &errors.Error{ 326 Code: errors.EInvalid, 327 Msg: "expected at least one attribute to be updated", 328 } 329 } 330 331 return nil 332 } 333 334 // Apply updates a view with the view updates properties. 335 func (u ViewUpdate) Apply(v *View) error { 336 if err := u.Valid(); err != nil { 337 return err 338 } 339 340 if u.Name != nil { 341 v.Name = *u.Name 342 } 343 344 if u.Properties != nil { 345 v.Properties = u.Properties 346 } 347 348 return nil 349 } 350 351 // ViewContentsUpdate is a struct for updating the non properties content of a View. 352 type ViewContentsUpdate struct { 353 Name *string `json:"name"` 354 } 355 356 // ViewFilter represents a set of filter that restrict the returned results. 357 type ViewFilter struct { 358 ID *platform.ID 359 Types []string 360 } 361 362 // View holds positional and visual information for a View. 363 type View struct { 364 ViewContents 365 Properties ViewProperties 366 } 367 368 // ViewContents is the id and name of a specific view. 369 type ViewContents struct { 370 ID platform.ID `json:"id,omitempty"` 371 Name string `json:"name"` 372 } 373 374 // Values for all supported view property types. 375 const ( 376 ViewPropertyTypeCheck = "check" 377 ViewPropertyTypeGauge = "gauge" 378 ViewPropertyTypeHeatMap = "heatmap" 379 ViewPropertyTypeHistogram = "histogram" 380 ViewPropertyTypeLogViewer = "log-viewer" 381 ViewPropertyTypeMarkdown = "markdown" 382 ViewPropertyTypeScatter = "scatter" 383 ViewPropertyTypeSingleStat = "single-stat" 384 ViewPropertyTypeSingleStatPlusLine = "line-plus-single-stat" 385 ViewPropertyTypeTable = "table" 386 ViewPropertyTypeXY = "xy" 387 ViewPropertyTypeMosaic = "mosaic" 388 ViewPropertyTypeBand = "band" 389 ViewPropertyTypeGeo = "geo" 390 ) 391 392 // ViewProperties is used to mark other structures as conforming to a View. 393 type ViewProperties interface { 394 viewProperties() 395 GetType() string 396 } 397 398 // EmptyViewProperties is visualization that has no values 399 type EmptyViewProperties struct{} 400 401 func (v EmptyViewProperties) viewProperties() {} 402 403 func (v EmptyViewProperties) GetType() string { return "" } 404 405 // UnmarshalViewPropertiesJSON unmarshals JSON bytes into a ViewProperties. 406 func UnmarshalViewPropertiesJSON(b []byte) (ViewProperties, error) { 407 var v struct { 408 B json.RawMessage `json:"properties"` 409 } 410 411 if err := json.Unmarshal(b, &v); err != nil { 412 return nil, err 413 } 414 415 if len(v.B) == 0 { 416 // Then there wasn't any visualization field, so there's no need unmarshal it 417 return EmptyViewProperties{}, nil 418 } 419 420 var t struct { 421 Shape string `json:"shape"` 422 Type string `json:"type"` 423 } 424 425 if err := json.Unmarshal(v.B, &t); err != nil { 426 return nil, err 427 } 428 429 var vis ViewProperties 430 switch t.Shape { 431 case "chronograf-v2": 432 switch t.Type { 433 case ViewPropertyTypeCheck: 434 var cv CheckViewProperties 435 if err := json.Unmarshal(v.B, &cv); err != nil { 436 return nil, err 437 } 438 vis = cv 439 case ViewPropertyTypeXY: 440 var xyv XYViewProperties 441 if err := json.Unmarshal(v.B, &xyv); err != nil { 442 return nil, err 443 } 444 vis = xyv 445 case ViewPropertyTypeSingleStat: 446 var ssv SingleStatViewProperties 447 if err := json.Unmarshal(v.B, &ssv); err != nil { 448 return nil, err 449 } 450 vis = ssv 451 case ViewPropertyTypeGauge: 452 var gv GaugeViewProperties 453 if err := json.Unmarshal(v.B, &gv); err != nil { 454 return nil, err 455 } 456 vis = gv 457 case ViewPropertyTypeGeo: 458 var gvw GeoViewProperties 459 if err := json.Unmarshal(v.B, &gvw); err != nil { 460 return nil, err 461 } 462 vis = gvw 463 case ViewPropertyTypeTable: 464 var tv TableViewProperties 465 if err := json.Unmarshal(v.B, &tv); err != nil { 466 return nil, err 467 } 468 vis = tv 469 case ViewPropertyTypeMarkdown: 470 var mv MarkdownViewProperties 471 if err := json.Unmarshal(v.B, &mv); err != nil { 472 return nil, err 473 } 474 vis = mv 475 case ViewPropertyTypeLogViewer: // happens in log viewer stays in log viewer. 476 var lv LogViewProperties 477 if err := json.Unmarshal(v.B, &lv); err != nil { 478 return nil, err 479 } 480 vis = lv 481 case ViewPropertyTypeSingleStatPlusLine: 482 var lv LinePlusSingleStatProperties 483 if err := json.Unmarshal(v.B, &lv); err != nil { 484 return nil, err 485 } 486 vis = lv 487 case ViewPropertyTypeHistogram: 488 var hv HistogramViewProperties 489 if err := json.Unmarshal(v.B, &hv); err != nil { 490 return nil, err 491 } 492 vis = hv 493 case ViewPropertyTypeHeatMap: 494 var hv HeatmapViewProperties 495 if err := json.Unmarshal(v.B, &hv); err != nil { 496 return nil, err 497 } 498 vis = hv 499 case ViewPropertyTypeScatter: 500 var sv ScatterViewProperties 501 if err := json.Unmarshal(v.B, &sv); err != nil { 502 return nil, err 503 } 504 vis = sv 505 case ViewPropertyTypeMosaic: 506 var mv MosaicViewProperties 507 if err := json.Unmarshal(v.B, &mv); err != nil { 508 return nil, err 509 } 510 vis = mv 511 case ViewPropertyTypeBand: 512 var bv BandViewProperties 513 if err := json.Unmarshal(v.B, &bv); err != nil { 514 return nil, err 515 } 516 vis = bv 517 } 518 case "empty": 519 var ev EmptyViewProperties 520 if err := json.Unmarshal(v.B, &ev); err != nil { 521 return nil, err 522 } 523 vis = ev 524 default: 525 return nil, fmt.Errorf("unknown shape %v", t.Shape) 526 } 527 528 return vis, nil 529 } 530 531 // MarshalViewPropertiesJSON encodes a view into JSON bytes. 532 func MarshalViewPropertiesJSON(v ViewProperties) ([]byte, error) { 533 var s interface{} 534 switch vis := v.(type) { 535 case SingleStatViewProperties: 536 s = struct { 537 Shape string `json:"shape"` 538 SingleStatViewProperties 539 }{ 540 Shape: "chronograf-v2", 541 542 SingleStatViewProperties: vis, 543 } 544 case TableViewProperties: 545 s = struct { 546 Shape string `json:"shape"` 547 TableViewProperties 548 }{ 549 Shape: "chronograf-v2", 550 551 TableViewProperties: vis, 552 } 553 case GaugeViewProperties: 554 s = struct { 555 Shape string `json:"shape"` 556 GaugeViewProperties 557 }{ 558 Shape: "chronograf-v2", 559 560 GaugeViewProperties: vis, 561 } 562 case GeoViewProperties: 563 s = struct { 564 Shape string `json:"shape"` 565 GeoViewProperties 566 }{ 567 Shape: "chronograf-v2", 568 GeoViewProperties: vis, 569 } 570 case XYViewProperties: 571 s = struct { 572 Shape string `json:"shape"` 573 XYViewProperties 574 }{ 575 Shape: "chronograf-v2", 576 577 XYViewProperties: vis, 578 } 579 case BandViewProperties: 580 s = struct { 581 Shape string `json:"shape"` 582 BandViewProperties 583 }{ 584 Shape: "chronograf-v2", 585 586 BandViewProperties: vis, 587 } 588 case LinePlusSingleStatProperties: 589 s = struct { 590 Shape string `json:"shape"` 591 LinePlusSingleStatProperties 592 }{ 593 Shape: "chronograf-v2", 594 595 LinePlusSingleStatProperties: vis, 596 } 597 case HistogramViewProperties: 598 s = struct { 599 Shape string `json:"shape"` 600 HistogramViewProperties 601 }{ 602 Shape: "chronograf-v2", 603 604 HistogramViewProperties: vis, 605 } 606 case HeatmapViewProperties: 607 s = struct { 608 Shape string `json:"shape"` 609 HeatmapViewProperties 610 }{ 611 Shape: "chronograf-v2", 612 613 HeatmapViewProperties: vis, 614 } 615 case ScatterViewProperties: 616 s = struct { 617 Shape string `json:"shape"` 618 ScatterViewProperties 619 }{ 620 Shape: "chronograf-v2", 621 622 ScatterViewProperties: vis, 623 } 624 case MosaicViewProperties: 625 s = struct { 626 Shape string `json:"shape"` 627 MosaicViewProperties 628 }{ 629 Shape: "chronograf-v2", 630 631 MosaicViewProperties: vis, 632 } 633 case MarkdownViewProperties: 634 s = struct { 635 Shape string `json:"shape"` 636 MarkdownViewProperties 637 }{ 638 Shape: "chronograf-v2", 639 640 MarkdownViewProperties: vis, 641 } 642 case LogViewProperties: 643 s = struct { 644 Shape string `json:"shape"` 645 LogViewProperties 646 }{ 647 Shape: "chronograf-v2", 648 LogViewProperties: vis, 649 } 650 case CheckViewProperties: 651 s = struct { 652 Shape string `json:"shape"` 653 CheckViewProperties 654 }{ 655 Shape: "chronograf-v2", 656 657 CheckViewProperties: vis, 658 } 659 default: 660 s = struct { 661 Shape string `json:"shape"` 662 EmptyViewProperties 663 }{ 664 Shape: "empty", 665 EmptyViewProperties: EmptyViewProperties{}, 666 } 667 } 668 return json.Marshal(s) 669 } 670 671 // MarshalJSON encodes a view to JSON bytes. 672 func (v View) MarshalJSON() ([]byte, error) { 673 viewProperties, err := MarshalViewPropertiesJSON(v.Properties) 674 if err != nil { 675 return nil, err 676 } 677 678 return json.Marshal(struct { 679 ViewContents 680 ViewProperties json.RawMessage `json:"properties"` 681 }{ 682 ViewContents: v.ViewContents, 683 ViewProperties: viewProperties, 684 }) 685 } 686 687 // UnmarshalJSON decodes JSON bytes into the corresponding view type (those that implement ViewProperties). 688 func (c *View) UnmarshalJSON(b []byte) error { 689 if err := json.Unmarshal(b, &c.ViewContents); err != nil { 690 return err 691 } 692 693 v, err := UnmarshalViewPropertiesJSON(b) 694 if err != nil { 695 return err 696 } 697 c.Properties = v 698 return nil 699 } 700 701 // UnmarshalJSON decodes JSON bytes into the corresponding view update type (those that implement ViewProperties). 702 func (u *ViewUpdate) UnmarshalJSON(b []byte) error { 703 if err := json.Unmarshal(b, &u.ViewContentsUpdate); err != nil { 704 return err 705 } 706 707 v, err := UnmarshalViewPropertiesJSON(b) 708 if err != nil { 709 return err 710 } 711 u.Properties = v 712 return nil 713 } 714 715 // MarshalJSON encodes a view to JSON bytes. 716 func (u ViewUpdate) MarshalJSON() ([]byte, error) { 717 vis, err := MarshalViewPropertiesJSON(u.Properties) 718 if err != nil { 719 return nil, err 720 } 721 722 return json.Marshal(struct { 723 ViewContentsUpdate 724 ViewProperties json.RawMessage `json:"properties,omitempty"` 725 }{ 726 ViewContentsUpdate: u.ViewContentsUpdate, 727 ViewProperties: vis, 728 }) 729 } 730 731 // LinePlusSingleStatProperties represents options for line plus single stat view in Chronograf 732 type LinePlusSingleStatProperties struct { 733 Queries []DashboardQuery `json:"queries"` 734 Axes map[string]Axis `json:"axes"` 735 Type string `json:"type"` 736 StaticLegend StaticLegend `json:"staticLegend"` 737 ViewColors []ViewColor `json:"colors"` 738 Prefix string `json:"prefix"` 739 Suffix string `json:"suffix"` 740 DecimalPlaces DecimalPlaces `json:"decimalPlaces"` 741 Note string `json:"note"` 742 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 743 XColumn string `json:"xColumn"` 744 GenerateXAxisTicks []string `json:"generateXAxisTicks"` 745 XTotalTicks int `json:"xTotalTicks"` 746 XTickStart float64 `json:"xTickStart"` 747 XTickStep float64 `json:"xTickStep"` 748 YColumn string `json:"yColumn"` 749 GenerateYAxisTicks []string `json:"generateYAxisTicks"` 750 YTotalTicks int `json:"yTotalTicks"` 751 YTickStart float64 `json:"yTickStart"` 752 YTickStep float64 `json:"yTickStep"` 753 ShadeBelow bool `json:"shadeBelow"` 754 Position string `json:"position"` 755 TimeFormat string `json:"timeFormat"` 756 HoverDimension string `json:"hoverDimension"` 757 LegendColorizeRows bool `json:"legendColorizeRows"` 758 LegendHide bool `json:"legendHide"` 759 LegendOpacity float64 `json:"legendOpacity"` 760 LegendOrientationThreshold int `json:"legendOrientationThreshold"` 761 } 762 763 // XYViewProperties represents options for line, bar, step, or stacked view in Chronograf 764 type XYViewProperties struct { 765 Queries []DashboardQuery `json:"queries"` 766 Axes map[string]Axis `json:"axes"` 767 Type string `json:"type"` 768 StaticLegend StaticLegend `json:"staticLegend"` 769 Geom string `json:"geom"` // Either "line", "step", "stacked", or "bar" 770 ViewColors []ViewColor `json:"colors"` 771 Note string `json:"note"` 772 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 773 XColumn string `json:"xColumn"` 774 GenerateXAxisTicks []string `json:"generateXAxisTicks"` 775 XTotalTicks int `json:"xTotalTicks"` 776 XTickStart float64 `json:"xTickStart"` 777 XTickStep float64 `json:"xTickStep"` 778 YColumn string `json:"yColumn"` 779 GenerateYAxisTicks []string `json:"generateYAxisTicks"` 780 YTotalTicks int `json:"yTotalTicks"` 781 YTickStart float64 `json:"yTickStart"` 782 YTickStep float64 `json:"yTickStep"` 783 ShadeBelow bool `json:"shadeBelow"` 784 Position string `json:"position"` 785 TimeFormat string `json:"timeFormat"` 786 HoverDimension string `json:"hoverDimension"` 787 LegendColorizeRows bool `json:"legendColorizeRows"` 788 LegendHide bool `json:"legendHide"` 789 LegendOpacity float64 `json:"legendOpacity"` 790 LegendOrientationThreshold int `json:"legendOrientationThreshold"` 791 } 792 793 // BandViewProperties represents options for the band view 794 type BandViewProperties struct { 795 Queries []DashboardQuery `json:"queries"` 796 Axes map[string]Axis `json:"axes"` 797 Type string `json:"type"` 798 StaticLegend StaticLegend `json:"staticLegend"` 799 Geom string `json:"geom"` 800 ViewColors []ViewColor `json:"colors"` 801 Note string `json:"note"` 802 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 803 TimeFormat string `json:"timeFormat"` 804 HoverDimension string `json:"hoverDimension"` 805 XColumn string `json:"xColumn"` 806 GenerateXAxisTicks []string `json:"generateXAxisTicks"` 807 XTotalTicks int `json:"xTotalTicks"` 808 XTickStart float64 `json:"xTickStart"` 809 XTickStep float64 `json:"xTickStep"` 810 YColumn string `json:"yColumn"` 811 GenerateYAxisTicks []string `json:"generateYAxisTicks"` 812 YTotalTicks int `json:"yTotalTicks"` 813 YTickStart float64 `json:"yTickStart"` 814 YTickStep float64 `json:"yTickStep"` 815 UpperColumn string `json:"upperColumn"` 816 MainColumn string `json:"mainColumn"` 817 LowerColumn string `json:"lowerColumn"` 818 LegendColorizeRows bool `json:"legendColorizeRows"` 819 LegendHide bool `json:"legendHide"` 820 LegendOpacity float64 `json:"legendOpacity"` 821 LegendOrientationThreshold int `json:"legendOrientationThreshold"` 822 } 823 824 // CheckViewProperties represents options for a view representing a check 825 type CheckViewProperties struct { 826 Type string `json:"type"` 827 CheckID string `json:"checkID"` 828 Queries []DashboardQuery `json:"queries"` 829 ViewColors []string `json:"colors"` 830 LegendColorizeRows bool `json:"legendColorizeRows"` 831 LegendHide bool `json:"legendHide"` 832 LegendOpacity float64 `json:"legendOpacity"` 833 LegendOrientationThreshold int `json:"legendOrientationThreshold"` 834 } 835 836 // SingleStatViewProperties represents options for single stat view in Chronograf 837 type SingleStatViewProperties struct { 838 Type string `json:"type"` 839 Queries []DashboardQuery `json:"queries"` 840 Prefix string `json:"prefix"` 841 TickPrefix string `json:"tickPrefix"` 842 Suffix string `json:"suffix"` 843 TickSuffix string `json:"tickSuffix"` 844 ViewColors []ViewColor `json:"colors"` 845 DecimalPlaces DecimalPlaces `json:"decimalPlaces"` 846 Note string `json:"note"` 847 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 848 } 849 850 // HistogramViewProperties represents options for histogram view in Chronograf 851 type HistogramViewProperties struct { 852 Type string `json:"type"` 853 Queries []DashboardQuery `json:"queries"` 854 ViewColors []ViewColor `json:"colors"` 855 XColumn string `json:"xColumn"` 856 FillColumns []string `json:"fillColumns"` 857 XDomain []float64 `json:"xDomain,omitempty"` 858 XAxisLabel string `json:"xAxisLabel"` 859 Position string `json:"position"` 860 BinCount int `json:"binCount"` 861 Note string `json:"note"` 862 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 863 LegendColorizeRows bool `json:"legendColorizeRows"` 864 LegendHide bool `json:"legendHide"` 865 LegendOpacity float64 `json:"legendOpacity"` 866 LegendOrientationThreshold int `json:"legendOrientationThreshold"` 867 } 868 869 // HeatmapViewProperties represents options for heatmap view in Chronograf 870 type HeatmapViewProperties struct { 871 Type string `json:"type"` 872 Queries []DashboardQuery `json:"queries"` 873 ViewColors []string `json:"colors"` 874 BinSize int32 `json:"binSize"` 875 XColumn string `json:"xColumn"` 876 GenerateXAxisTicks []string `json:"generateXAxisTicks"` 877 XTotalTicks int `json:"xTotalTicks"` 878 XTickStart float64 `json:"xTickStart"` 879 XTickStep float64 `json:"xTickStep"` 880 YColumn string `json:"yColumn"` 881 GenerateYAxisTicks []string `json:"generateYAxisTicks"` 882 YTotalTicks int `json:"yTotalTicks"` 883 YTickStart float64 `json:"yTickStart"` 884 YTickStep float64 `json:"yTickStep"` 885 XDomain []float64 `json:"xDomain,omitempty"` 886 YDomain []float64 `json:"yDomain,omitempty"` 887 XAxisLabel string `json:"xAxisLabel"` 888 YAxisLabel string `json:"yAxisLabel"` 889 XPrefix string `json:"xPrefix"` 890 XSuffix string `json:"xSuffix"` 891 YPrefix string `json:"yPrefix"` 892 YSuffix string `json:"ySuffix"` 893 Note string `json:"note"` 894 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 895 TimeFormat string `json:"timeFormat"` 896 LegendColorizeRows bool `json:"legendColorizeRows"` 897 LegendHide bool `json:"legendHide"` 898 LegendOpacity float64 `json:"legendOpacity"` 899 LegendOrientationThreshold int `json:"legendOrientationThreshold"` 900 } 901 902 // ScatterViewProperties represents options for scatter view in Chronograf 903 type ScatterViewProperties struct { 904 Type string `json:"type"` 905 Queries []DashboardQuery `json:"queries"` 906 ViewColors []string `json:"colors"` 907 FillColumns []string `json:"fillColumns"` 908 SymbolColumns []string `json:"symbolColumns"` 909 XColumn string `json:"xColumn"` 910 GenerateXAxisTicks []string `json:"generateXAxisTicks"` 911 XTotalTicks int `json:"xTotalTicks"` 912 XTickStart float64 `json:"xTickStart"` 913 XTickStep float64 `json:"xTickStep"` 914 YColumn string `json:"yColumn"` 915 GenerateYAxisTicks []string `json:"generateYAxisTicks"` 916 YTotalTicks int `json:"yTotalTicks"` 917 YTickStart float64 `json:"yTickStart"` 918 YTickStep float64 `json:"yTickStep"` 919 XDomain []float64 `json:"xDomain,omitempty"` 920 YDomain []float64 `json:"yDomain,omitempty"` 921 XAxisLabel string `json:"xAxisLabel"` 922 YAxisLabel string `json:"yAxisLabel"` 923 XPrefix string `json:"xPrefix"` 924 XSuffix string `json:"xSuffix"` 925 YPrefix string `json:"yPrefix"` 926 YSuffix string `json:"ySuffix"` 927 Note string `json:"note"` 928 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 929 TimeFormat string `json:"timeFormat"` 930 LegendColorizeRows bool `json:"legendColorizeRows"` 931 LegendHide bool `json:"legendHide"` 932 LegendOpacity float64 `json:"legendOpacity"` 933 LegendOrientationThreshold int `json:"legendOrientationThreshold"` 934 } 935 936 // MosaicViewProperties represents options for mosaic view in Chronograf 937 type MosaicViewProperties struct { 938 Type string `json:"type"` 939 Queries []DashboardQuery `json:"queries"` 940 ViewColors []string `json:"colors"` 941 FillColumns []string `json:"fillColumns"` 942 XColumn string `json:"xColumn"` 943 GenerateXAxisTicks []string `json:"generateXAxisTicks"` 944 XTotalTicks int `json:"xTotalTicks"` 945 XTickStart float64 `json:"xTickStart"` 946 XTickStep float64 `json:"xTickStep"` 947 YLabelColumnSeparator string `json:"yLabelColumnSeparator"` 948 YLabelColumns []string `json:"yLabelColumns"` 949 YSeriesColumns []string `json:"ySeriesColumns"` 950 XDomain []float64 `json:"xDomain,omitempty"` 951 YDomain []float64 `json:"yDomain,omitempty"` 952 XAxisLabel string `json:"xAxisLabel"` 953 YAxisLabel string `json:"yAxisLabel"` 954 XPrefix string `json:"xPrefix"` 955 XSuffix string `json:"xSuffix"` 956 YPrefix string `json:"yPrefix"` 957 YSuffix string `json:"ySuffix"` 958 Note string `json:"note"` 959 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 960 TimeFormat string `json:"timeFormat"` 961 HoverDimension string `json:"hoverDimension"` 962 LegendColorizeRows bool `json:"legendColorizeRows"` 963 LegendHide bool `json:"legendHide"` 964 LegendOpacity float64 `json:"legendOpacity"` 965 LegendOrientationThreshold int `json:"legendOrientationThreshold"` 966 } 967 968 // GaugeViewProperties represents options for gauge view in Chronograf 969 type GaugeViewProperties struct { 970 Type string `json:"type"` 971 Queries []DashboardQuery `json:"queries"` 972 Prefix string `json:"prefix"` 973 TickPrefix string `json:"tickPrefix"` 974 Suffix string `json:"suffix"` 975 TickSuffix string `json:"tickSuffix"` 976 ViewColors []ViewColor `json:"colors"` 977 DecimalPlaces DecimalPlaces `json:"decimalPlaces"` 978 Note string `json:"note"` 979 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 980 } 981 982 // Geographical coordinates 983 type Datum struct { 984 Lat float64 `json:"lat"` 985 Lon float64 `json:"lon"` 986 } 987 988 // Single visualization layer properties of a chronograf map widget 989 type GeoLayer struct { 990 Type string `json:"type"` 991 RadiusField string `json:"radiusField"` 992 ColorField string `json:"colorField"` 993 IntensityField string `json:"intensityField"` 994 // circle layer properties 995 ViewColors []ViewColor `json:"colors"` 996 Radius int32 `json:"radius"` 997 Blur int32 `json:"blur"` 998 RadiusDimension Axis `json:"radiusDimension,omitempty"` 999 ColorDimension Axis `json:"colorDimension,omitempty"` 1000 IntensityDimension Axis `json:"intensityDimension,omitempty"` 1001 InterpolateColors bool `json:"interpolateColors"` 1002 // track layer properties 1003 TrackWidth int32 `json:"trackWidth"` 1004 Speed int32 `json:"speed"` 1005 RandomColors bool `json:"randomColors"` 1006 // point layer properties 1007 IsClustered bool `json:"isClustered"` 1008 } 1009 1010 // GeoViewProperties represents options for map view in Chronograf 1011 type GeoViewProperties struct { 1012 Type string `json:"type"` 1013 Queries []DashboardQuery `json:"queries"` 1014 Center Datum `json:"center"` 1015 Zoom float64 `json:"zoom"` 1016 MapStyle string `json:"mapStyle"` 1017 AllowPanAndZoom bool `json:"allowPanAndZoom"` 1018 DetectCoordinateFields bool `json:"detectCoordinateFields"` 1019 ViewColor []ViewColor `json:"colors"` 1020 GeoLayers []GeoLayer `json:"layers"` 1021 Note string `json:"note"` 1022 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 1023 } 1024 1025 // TableViewProperties represents options for table view in Chronograf 1026 type TableViewProperties struct { 1027 Type string `json:"type"` 1028 Queries []DashboardQuery `json:"queries"` 1029 ViewColors []ViewColor `json:"colors"` 1030 TableOptions TableOptions `json:"tableOptions"` 1031 FieldOptions []RenamableField `json:"fieldOptions"` 1032 TimeFormat string `json:"timeFormat"` 1033 DecimalPlaces DecimalPlaces `json:"decimalPlaces"` 1034 Note string `json:"note"` 1035 ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` 1036 } 1037 1038 type MarkdownViewProperties struct { 1039 Type string `json:"type"` 1040 Note string `json:"note"` 1041 } 1042 1043 // LogViewProperties represents options for log viewer in Chronograf. 1044 type LogViewProperties struct { 1045 Type string `json:"type"` 1046 Columns []LogViewerColumn `json:"columns"` 1047 } 1048 1049 // LogViewerColumn represents a specific column in a Log Viewer. 1050 type LogViewerColumn struct { 1051 Name string `json:"name"` 1052 Position int32 `json:"position"` 1053 Settings []LogColumnSetting `json:"settings"` 1054 } 1055 1056 // LogColumnSetting represent the settings for a specific column of a Log Viewer. 1057 type LogColumnSetting struct { 1058 Type string `json:"type"` 1059 Value string `json:"value"` 1060 Name string `json:"name,omitempty"` 1061 } 1062 1063 func (XYViewProperties) viewProperties() {} 1064 func (BandViewProperties) viewProperties() {} 1065 func (LinePlusSingleStatProperties) viewProperties() {} 1066 func (SingleStatViewProperties) viewProperties() {} 1067 func (HistogramViewProperties) viewProperties() {} 1068 func (HeatmapViewProperties) viewProperties() {} 1069 func (ScatterViewProperties) viewProperties() {} 1070 func (MosaicViewProperties) viewProperties() {} 1071 func (GaugeViewProperties) viewProperties() {} 1072 func (GeoViewProperties) viewProperties() {} 1073 func (TableViewProperties) viewProperties() {} 1074 func (MarkdownViewProperties) viewProperties() {} 1075 func (LogViewProperties) viewProperties() {} 1076 func (CheckViewProperties) viewProperties() {} 1077 1078 func (v XYViewProperties) GetType() string { return v.Type } 1079 func (v BandViewProperties) GetType() string { return v.Type } 1080 func (v LinePlusSingleStatProperties) GetType() string { return v.Type } 1081 func (v SingleStatViewProperties) GetType() string { return v.Type } 1082 func (v HistogramViewProperties) GetType() string { return v.Type } 1083 func (v HeatmapViewProperties) GetType() string { return v.Type } 1084 func (v ScatterViewProperties) GetType() string { return v.Type } 1085 func (v MosaicViewProperties) GetType() string { return v.Type } 1086 func (v GaugeViewProperties) GetType() string { return v.Type } 1087 func (v GeoViewProperties) GetType() string { return v.Type } 1088 func (v TableViewProperties) GetType() string { return v.Type } 1089 func (v MarkdownViewProperties) GetType() string { return v.Type } 1090 func (v LogViewProperties) GetType() string { return v.Type } 1091 func (v CheckViewProperties) GetType() string { return v.Type } 1092 1093 ///////////////////////////// 1094 // Old Chronograf Types 1095 ///////////////////////////// 1096 1097 // DashboardQuery represents a query used in a dashboard cell 1098 type DashboardQuery struct { 1099 Text string `json:"text"` 1100 EditMode string `json:"editMode"` // Either "builder" or "advanced" 1101 Name string `json:"name"` // Term or phrase that refers to the query 1102 BuilderConfig BuilderConfig `json:"builderConfig"` 1103 } 1104 1105 type BuilderConfig struct { 1106 Buckets []string `json:"buckets"` 1107 Tags []struct { 1108 Key string `json:"key"` 1109 Values []string `json:"values"` 1110 AggregateFunctionType string `json:"aggregateFunctionType"` 1111 } `json:"tags"` 1112 Functions []struct { 1113 Name string `json:"name"` 1114 } `json:"functions"` 1115 AggregateWindow struct { 1116 Period string `json:"period"` 1117 FillValues bool `json:"fillValues"` 1118 } `json:"aggregateWindow"` 1119 } 1120 1121 // MarshalJSON is necessary for the time being. UI keeps breaking 1122 // b/c it relies on these slices being populated/not nil. Other 1123 // consumers may have same issue. 1124 func (b BuilderConfig) MarshalJSON() ([]byte, error) { 1125 type alias BuilderConfig 1126 copyCfg := alias(b) 1127 if copyCfg.Buckets == nil { 1128 copyCfg.Buckets = []string{} 1129 } 1130 if copyCfg.Tags == nil { 1131 copyCfg.Tags = []struct { 1132 Key string `json:"key"` 1133 Values []string `json:"values"` 1134 AggregateFunctionType string `json:"aggregateFunctionType"` 1135 }{} 1136 } 1137 if copyCfg.Functions == nil { 1138 copyCfg.Functions = []struct { 1139 Name string `json:"name"` 1140 }{} 1141 } 1142 return json.Marshal(copyCfg) 1143 } 1144 1145 // NewBuilderTag is a constructor for the builder config types. This 1146 // isn't technically required, but working with struct literals with embedded 1147 // struct tags is really painful. This is to get around that bit. Would be nicer 1148 // to have these as actual types maybe. 1149 func NewBuilderTag(key string, functionType string, values ...string) struct { 1150 Key string `json:"key"` 1151 Values []string `json:"values"` 1152 AggregateFunctionType string `json:"aggregateFunctionType"` 1153 } { 1154 return struct { 1155 Key string `json:"key"` 1156 Values []string `json:"values"` 1157 AggregateFunctionType string `json:"aggregateFunctionType"` 1158 }{ 1159 Key: key, 1160 Values: values, 1161 AggregateFunctionType: functionType, 1162 } 1163 } 1164 1165 // Axis represents the visible extents of a visualization 1166 type Axis struct { 1167 Bounds []string `json:"bounds"` // bounds are an arbitrary list of client-defined strings that specify the viewport for a View 1168 LegacyBounds [2]int64 `json:"-"` // legacy bounds are for testing a migration from an earlier version of axis 1169 Label string `json:"label"` // label is a description of this Axis 1170 Prefix string `json:"prefix"` // Prefix represents a label prefix for formatting axis values 1171 Suffix string `json:"suffix"` // Suffix represents a label suffix for formatting axis values 1172 Base string `json:"base"` // Base represents the radix for formatting axis values 1173 Scale string `json:"scale"` // Scale is the axis formatting scale. Supported: "log", "linear" 1174 } 1175 1176 // ViewColor represents the encoding of data into visualizations 1177 type ViewColor struct { 1178 ID string `json:"id"` // ID is the unique id of the View color 1179 Type string `json:"type"` // Type is how the color is used. Accepted (min,max,threshold) 1180 Hex string `json:"hex"` // Hex is the hex number of the color 1181 Name string `json:"name"` // Name is the user-facing name of the hex color 1182 Value float64 `json:"value"` // Value is the data value mapped to this color 1183 } 1184 1185 // StaticLegend represents the options specific to the static legend 1186 type StaticLegend struct { 1187 ColorizeRows bool `json:"colorizeRows,omitempty"` 1188 HeightRatio float64 `json:"heightRatio,omitempty"` 1189 Show bool `json:"show,omitempty"` 1190 Opacity float64 `json:"opacity,omitempty"` 1191 OrientationThreshold int `json:"orientationThreshold,omitempty"` 1192 ValueAxis string `json:"valueAxis,omitempty"` 1193 WidthRatio float64 `json:"widthRatio,omitempty"` 1194 } 1195 1196 // TableOptions is a type of options for a DashboardView with type Table 1197 type TableOptions struct { 1198 VerticalTimeAxis bool `json:"verticalTimeAxis"` 1199 SortBy RenamableField `json:"sortBy"` 1200 Wrapping string `json:"wrapping"` 1201 FixFirstColumn bool `json:"fixFirstColumn"` 1202 } 1203 1204 // RenamableField is a column/row field in a DashboardView of type Table 1205 type RenamableField struct { 1206 InternalName string `json:"internalName"` 1207 DisplayName string `json:"displayName"` 1208 Visible bool `json:"visible"` 1209 } 1210 1211 // DecimalPlaces indicates whether decimal places should be enforced, and how many digits it should show. 1212 type DecimalPlaces struct { 1213 IsEnforced bool `json:"isEnforced"` 1214 Digits int32 `json:"digits"` 1215 }