monitor.go raw

   1  // Copyright 2022-2025 The sacloud/iaas-api-go Authors
   2  //
   3  // Licensed under the Apache License, Version 2.0 (the "License");
   4  // you may not use this file except in compliance with the License.
   5  // You may obtain a copy of the License at
   6  //
   7  //      http://www.apache.org/licenses/LICENSE-2.0
   8  //
   9  // Unless required by applicable law or agreed to in writing, software
  10  // distributed under the License is distributed on an "AS IS" BASIS,
  11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12  // See the License for the specific language governing permissions and
  13  // limitations under the License.
  14  
  15  package naked
  16  
  17  import (
  18  	"encoding/json"
  19  	"sort"
  20  	"strings"
  21  	"time"
  22  )
  23  
  24  // MonitorValues アクティビティモニタのレスポンス向け汎用エンベロープ
  25  type MonitorValues struct {
  26  	// CPU CPU-TIME
  27  	CPU MonitorCPUTimeValues
  28  	// Disk Read/Write
  29  	Disk MonitorDiskValues
  30  	// Interface Send/Receive
  31  	Interface MonitorInterfaceValues
  32  	// Router In/Out
  33  	Router MonitorRouterValues
  34  	// Database データベース
  35  	Database MonitorDatabaseValues
  36  	// FreeDiskSize 空きディスクサイズ(NFS)
  37  	FreeDiskSize MonitorFreeDiskSizeValues
  38  	// ResponseTimeSec 応答時間(シンプル監視)
  39  	ResponseTimeSec MonitorResponseTimeSecValues
  40  	// Link UplinkBPS/DownlinkBPS
  41  	Link MonitorLinkValues
  42  	// Connection 接続数
  43  	Connection MonitorConnectionValues
  44  	// LocalRouter Receive/Send bytes per sec
  45  	LocalRouter MonitorLocalRouterValues
  46  }
  47  
  48  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
  49  func (m *MonitorValues) UnmarshalJSON(data []byte) error {
  50  	v := MonitorValues{}
  51  
  52  	// CPU
  53  	if err := json.Unmarshal(data, &v.CPU); err != nil {
  54  		return nil
  55  	}
  56  	if len(v.CPU) > 0 {
  57  		*m = v
  58  		return nil
  59  	}
  60  
  61  	//	Disk
  62  	if err := json.Unmarshal(data, &v.Disk); err != nil {
  63  		return nil
  64  	}
  65  	if len(v.Disk) > 0 {
  66  		*m = v
  67  		return nil
  68  	}
  69  
  70  	//	Interface
  71  	if err := json.Unmarshal(data, &v.Interface); err != nil {
  72  		return nil
  73  	}
  74  	if len(v.Interface) > 0 {
  75  		*m = v
  76  		return nil
  77  	}
  78  
  79  	//	Router
  80  	if err := json.Unmarshal(data, &v.Router); err != nil {
  81  		return nil
  82  	}
  83  	if len(v.Router) > 0 {
  84  		*m = v
  85  		return nil
  86  	}
  87  
  88  	//	Database
  89  	if err := json.Unmarshal(data, &v.Database); err != nil {
  90  		return nil
  91  	}
  92  	if len(v.Database) > 0 {
  93  		*m = v
  94  		return nil
  95  	}
  96  
  97  	//	FreeDiskSize
  98  	if err := json.Unmarshal(data, &v.FreeDiskSize); err != nil {
  99  		return nil
 100  	}
 101  	if len(v.FreeDiskSize) > 0 {
 102  		*m = v
 103  		return nil
 104  	}
 105  
 106  	//	ResponseTimeSec
 107  	if err := json.Unmarshal(data, &v.ResponseTimeSec); err != nil {
 108  		return nil
 109  	}
 110  	if len(v.ResponseTimeSec) > 0 {
 111  		*m = v
 112  		return nil
 113  	}
 114  
 115  	//	Link
 116  	if err := json.Unmarshal(data, &v.Link); err != nil {
 117  		return nil
 118  	}
 119  	if len(v.Link) > 0 {
 120  		*m = v
 121  		return nil
 122  	}
 123  
 124  	//	Connection
 125  	if err := json.Unmarshal(data, &v.Connection); err != nil {
 126  		return nil
 127  	}
 128  	if len(v.Connection) > 0 {
 129  		*m = v
 130  		return nil
 131  	}
 132  
 133  	//	LocalRouter
 134  	if err := json.Unmarshal(data, &v.LocalRouter); err != nil {
 135  		return nil
 136  	}
 137  	if len(v.LocalRouter) > 0 {
 138  		*m = v
 139  		return nil
 140  	}
 141  	return nil
 142  }
 143  
 144  /************************************************
 145   * CPU-TIME
 146  ************************************************/
 147  
 148  // MonitorCPUTimeValue CPU-TIMEアクティビティモニタ
 149  type MonitorCPUTimeValue struct {
 150  	Time    time.Time // 対象時刻
 151  	CPUTime float64
 152  }
 153  
 154  // MonitorCPUTimeValues CPU-TIMEアクティビティモニタ
 155  type MonitorCPUTimeValues []*MonitorCPUTimeValue
 156  
 157  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
 158  func (m *MonitorCPUTimeValues) UnmarshalJSON(data []byte) error {
 159  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 160  	if targetData == `[]` {
 161  		return nil
 162  	}
 163  
 164  	var rawMonitorValues rawMonitorValues
 165  	if err := json.Unmarshal(data, &rawMonitorValues); err != nil {
 166  		return err
 167  	}
 168  	values, err := rawMonitorValues.monitorCPUTimeValues()
 169  	if err != nil {
 170  		return err
 171  	}
 172  
 173  	*m = values
 174  	return nil
 175  }
 176  
 177  /************************************************
 178   * Disk(Read/Write)
 179  ************************************************/
 180  
 181  // MonitorDiskValue アクティビティモニタ
 182  type MonitorDiskValue struct {
 183  	Time  time.Time
 184  	Write float64
 185  	Read  float64
 186  }
 187  
 188  // MonitorDiskValues アクティビティモニタ
 189  type MonitorDiskValues []*MonitorDiskValue
 190  
 191  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
 192  func (m *MonitorDiskValues) UnmarshalJSON(data []byte) error {
 193  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 194  	if targetData == `[]` {
 195  		return nil
 196  	}
 197  
 198  	var rawMonitorValues rawMonitorValues
 199  	if err := json.Unmarshal(data, &rawMonitorValues); err != nil {
 200  		return err
 201  	}
 202  	values, err := rawMonitorValues.monitorDiskValues()
 203  	if err != nil {
 204  		return err
 205  	}
 206  
 207  	*m = values
 208  	return nil
 209  }
 210  
 211  /************************************************
 212   * Interface(Send/Receive)
 213  ************************************************/
 214  
 215  // MonitorInterfaceValue アクティビティモニタ
 216  type MonitorInterfaceValue struct {
 217  	Time    time.Time
 218  	Send    float64
 219  	Receive float64
 220  }
 221  
 222  // MonitorInterfaceValues アクティビティモニタ
 223  type MonitorInterfaceValues []*MonitorInterfaceValue
 224  
 225  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
 226  func (m *MonitorInterfaceValues) UnmarshalJSON(data []byte) error {
 227  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 228  	if targetData == `[]` {
 229  		return nil
 230  	}
 231  
 232  	var rawMonitorValues rawMonitorValues
 233  	if err := json.Unmarshal(data, &rawMonitorValues); err != nil {
 234  		return err
 235  	}
 236  	values, err := rawMonitorValues.monitorInterfaceValues()
 237  	if err != nil {
 238  		return err
 239  	}
 240  
 241  	*m = values
 242  	return nil
 243  }
 244  
 245  /************************************************
 246   * Router(In/Out)
 247  ************************************************/
 248  
 249  // MonitorRouterValue アクティビティモニタ
 250  type MonitorRouterValue struct {
 251  	Time time.Time
 252  	In   float64
 253  	Out  float64
 254  }
 255  
 256  // MonitorRouterValues アクティビティモニタ
 257  type MonitorRouterValues []*MonitorRouterValue
 258  
 259  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
 260  func (m *MonitorRouterValues) UnmarshalJSON(data []byte) error {
 261  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 262  	if targetData == `[]` {
 263  		return nil
 264  	}
 265  
 266  	var rawMonitorValues rawMonitorValues
 267  	if err := json.Unmarshal(data, &rawMonitorValues); err != nil {
 268  		return err
 269  	}
 270  	values, err := rawMonitorValues.monitorRouterValues()
 271  	if err != nil {
 272  		return err
 273  	}
 274  
 275  	*m = values
 276  	return nil
 277  }
 278  
 279  /************************************************
 280   * Database
 281  ************************************************/
 282  
 283  // MonitorDatabaseValue アクティビティモニタ
 284  type MonitorDatabaseValue struct {
 285  	Time              time.Time // 対象時刻
 286  	TotalMemorySize   float64
 287  	UsedMemorySize    float64
 288  	TotalDisk1Size    float64
 289  	UsedDisk1Size     float64
 290  	TotalDisk2Size    float64
 291  	UsedDisk2Size     float64
 292  	BinlogUsedSizeKiB float64
 293  	DelayTimeSec      float64
 294  }
 295  
 296  // MonitorDatabaseValues アクティビティモニタ
 297  type MonitorDatabaseValues []*MonitorDatabaseValue
 298  
 299  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
 300  func (m *MonitorDatabaseValues) UnmarshalJSON(data []byte) error {
 301  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 302  	if targetData == `[]` {
 303  		return nil
 304  	}
 305  
 306  	var rawMonitorValues rawMonitorValues
 307  	if err := json.Unmarshal(data, &rawMonitorValues); err != nil {
 308  		return err
 309  	}
 310  	values, err := rawMonitorValues.monitorDatabaseValues()
 311  	if err != nil {
 312  		return err
 313  	}
 314  
 315  	*m = values
 316  	return nil
 317  }
 318  
 319  /************************************************
 320   * FreeDiskSize
 321  ************************************************/
 322  
 323  // MonitorFreeDiskSizeValue アクティビティモニタ
 324  type MonitorFreeDiskSizeValue struct {
 325  	Time         time.Time // 対象時刻
 326  	FreeDiskSize float64
 327  }
 328  
 329  // MonitorFreeDiskSizeValues アクティビティモニタ
 330  type MonitorFreeDiskSizeValues []*MonitorFreeDiskSizeValue
 331  
 332  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
 333  func (m *MonitorFreeDiskSizeValues) UnmarshalJSON(data []byte) error {
 334  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 335  	if targetData == `[]` {
 336  		return nil
 337  	}
 338  
 339  	var rawMonitorValues rawMonitorValues
 340  	if err := json.Unmarshal(data, &rawMonitorValues); err != nil {
 341  		return err
 342  	}
 343  	values, err := rawMonitorValues.monitorFreeDiskSizeValues()
 344  	if err != nil {
 345  		return err
 346  	}
 347  
 348  	*m = values
 349  	return nil
 350  }
 351  
 352  /************************************************
 353   * ResponseTimeSec
 354  ************************************************/
 355  
 356  // MonitorResponseTimeSecValue アクティビティモニタ
 357  type MonitorResponseTimeSecValue struct {
 358  	Time            time.Time // 対象時刻
 359  	ResponseTimeSec float64
 360  }
 361  
 362  // MonitorResponseTimeSecValues アクティビティモニタ
 363  type MonitorResponseTimeSecValues []*MonitorResponseTimeSecValue
 364  
 365  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
 366  func (m *MonitorResponseTimeSecValues) UnmarshalJSON(data []byte) error {
 367  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 368  	if targetData == `[]` {
 369  		return nil
 370  	}
 371  
 372  	var rawMonitorValues rawMonitorValues
 373  	if err := json.Unmarshal(data, &rawMonitorValues); err != nil {
 374  		return err
 375  	}
 376  	values, err := rawMonitorValues.monitorResponseTimeSecValues()
 377  	if err != nil {
 378  		return err
 379  	}
 380  
 381  	*m = values
 382  	return nil
 383  }
 384  
 385  /************************************************
 386   * Link(up/down)
 387  ************************************************/
 388  
 389  // MonitorLinkValue アクティビティモニタ
 390  type MonitorLinkValue struct {
 391  	Time        time.Time
 392  	UplinkBPS   float64
 393  	DownlinkBPS float64
 394  }
 395  
 396  // MonitorLinkValues アクティビティモニタ
 397  type MonitorLinkValues []*MonitorLinkValue
 398  
 399  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
 400  func (m *MonitorLinkValues) UnmarshalJSON(data []byte) error {
 401  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 402  	if targetData == `[]` {
 403  		return nil
 404  	}
 405  
 406  	var rawMonitorValues rawMonitorValues
 407  	if err := json.Unmarshal(data, &rawMonitorValues); err != nil {
 408  		return err
 409  	}
 410  	values, err := rawMonitorValues.monitorLinkValues()
 411  	if err != nil {
 412  		return err
 413  	}
 414  
 415  	*m = values
 416  	return nil
 417  }
 418  
 419  /************************************************
 420   * Connection(ProxyLB)
 421  ************************************************/
 422  
 423  // MonitorConnectionValue アクティビティモニタ
 424  type MonitorConnectionValue struct {
 425  	Time              time.Time
 426  	ActiveConnections float64
 427  	ConnectionsPerSec float64
 428  }
 429  
 430  // MonitorConnectionValues アクティビティモニタ
 431  type MonitorConnectionValues []*MonitorConnectionValue
 432  
 433  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
 434  func (m *MonitorConnectionValues) UnmarshalJSON(data []byte) error {
 435  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 436  	if targetData == `[]` {
 437  		return nil
 438  	}
 439  
 440  	var rawMonitorValues rawMonitorValues
 441  	if err := json.Unmarshal(data, &rawMonitorValues); err != nil {
 442  		return err
 443  	}
 444  	values, err := rawMonitorValues.monitorConnectionValues()
 445  	if err != nil {
 446  		return err
 447  	}
 448  
 449  	*m = values
 450  	return nil
 451  }
 452  
 453  /************************************************
 454   * LocalRouter(Receive/Send BytesPerSec)
 455  ************************************************/
 456  
 457  // MonitorLocalRouterValue アクティビティモニタ
 458  type MonitorLocalRouterValue struct {
 459  	Time               time.Time
 460  	ReceiveBytesPerSec float64
 461  	SendBytesPerSec    float64
 462  }
 463  
 464  // MonitorLocalRouterValues アクティビティモニタ
 465  type MonitorLocalRouterValues []*MonitorLocalRouterValue
 466  
 467  // UnmarshalJSON アクティビティモニタ向けUnmarshalJSON実装
 468  func (m *MonitorLocalRouterValues) UnmarshalJSON(data []byte) error {
 469  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 470  	if targetData == `[]` {
 471  		return nil
 472  	}
 473  
 474  	var rawMonitorValues rawMonitorValues
 475  	if err := json.Unmarshal(data, &rawMonitorValues); err != nil {
 476  		return err
 477  	}
 478  	values, err := rawMonitorValues.monitorLocalRouterValues()
 479  	if err != nil {
 480  		return err
 481  	}
 482  
 483  	*m = values
 484  	return nil
 485  }
 486  
 487  // rawMonitorValue アクティビティモニター
 488  type rawMonitorValue struct {
 489  	CPUTime            *float64 `json:"CPU-TIME,omitempty" yaml:"cpu_timme,omitempty" structs:",omitempty"`                       // CPU時間
 490  	Write              *float64 `json:",omitempty" yaml:"write,omitempty" structs:",omitempty"`                                   // ディスク書き込み
 491  	Read               *float64 `json:",omitempty" yaml:"read,omitempty" structs:",omitempty"`                                    // ディスク読み取り
 492  	Receive            *float64 `json:",omitempty" yaml:"receive,omitempty" structs:",omitempty"`                                 // パケット受信
 493  	Send               *float64 `json:",omitempty" yaml:"send,omitempty" structs:",omitempty"`                                    // パケット送信
 494  	In                 *float64 `json:",omitempty" yaml:"in,omitempty" structs:",omitempty"`                                      // パケット受信
 495  	Out                *float64 `json:",omitempty" yaml:"out,omitempty" structs:",omitempty"`                                     // パケット送信
 496  	TotalMemorySize    *float64 `json:"Total-Memory-Size,omitempty" yaml:"total_memory_size,omitempty" structs:",omitempty"`      // 総メモリサイズ
 497  	UsedMemorySize     *float64 `json:"Used-Memory-Size,omitempty" yaml:"used_memory_size,omitempty" structs:",omitempty"`        // 使用済みメモリサイズ
 498  	TotalDisk1Size     *float64 `json:"Total-Disk1-Size,omitempty" yaml:"total_disk1_size,omitempty" structs:",omitempty"`        // 総ディスクサイズ
 499  	UsedDisk1Size      *float64 `json:"Used-Disk1-Size,omitempty" yaml:"used_disk1_size,omitempty" structs:",omitempty"`          // 使用済みディスクサイズ
 500  	TotalDisk2Size     *float64 `json:"Total-Disk2-Size,omitempty" yaml:"total_disk2_size,omitempty" structs:",omitempty"`        // 総ディスクサイズ
 501  	UsedDisk2Size      *float64 `json:"Used-Disk2-Size,omitempty" yaml:"used_disk2_size,omitempty" structs:",omitempty"`          // 使用済みディスクサイズ
 502  	BinlogUsedSizeKiB  *float64 `json:"binlogUsedSizeKiB,omitempty" yaml:"binlog_used_size_kib,omitempty" structs:",omitempty"`   // バイナリログのサイズ(レプリケーション有効時のみ、master/slave両方で利用可能)
 503  	DelayTimeSec       *float64 `json:"delayTimeSec,omitempty" yaml:"delay_time_sec,omitempty" structs:",omitempty"`              // レプリケーション遅延時間(レプリケーション有効時のみ、slave側のみ)
 504  	FreeDiskSize       *float64 `json:"Free-Disk-Size,omitempty" yaml:"free_disk_size,omitempty" structs:",omitempty"`            // 空きディスクサイズ(NFS)
 505  	ResponseTimeSec    *float64 `json:"responsetimesec,omitempty" yaml:"response_time_sec,omitempty" structs:",omitempty"`        // レスポンスタイム(シンプル監視)
 506  	UplinkBPS          *float64 `json:"UplinkBps,omitempty" yaml:"uplink_bps,omitempty" structs:",omitempty"`                     // 上り方向トラフィック
 507  	DownlinkBPS        *float64 `json:"DownlinkBps,omitempty" yaml:"downlink_bps,omitempty" structs:",omitempty"`                 // 下り方向トラフィック
 508  	ActiveConnections  *float64 `json:"activeConnections,omitempty" yaml:"active_connections,omitempty" structs:",omitempty"`     // アクティブコネクション(プロキシLB)
 509  	ConnectionsPerSec  *float64 `json:"connectionsPerSec,omitempty" yaml:"connections_per_sec,omitempty" structs:",omitempty"`    // 秒間コネクション数
 510  	ReceiveBytesPerSec *float64 `json:"receiveBytesPerSec,omitempty" yaml:"receive_bytes_per_sec,omitempty" structs:",omitempty"` // 秒間受信バイト数
 511  	SendBytesPerSec    *float64 `json:"sendBytesPerSec,omitempty" yaml:"send_bytes_per_sec,omitempty" structs:",omitempty"`       // 秒間送信バイト数
 512  }
 513  
 514  // UnmarshalJSON JSONアンマーシャル(配列、オブジェクトが混在するためここで対応)
 515  func (m *rawMonitorValue) UnmarshalJSON(data []byte) error {
 516  	targetData := strings.ReplaceAll(strings.ReplaceAll(string(data), " ", ""), "\n", "")
 517  	if targetData == `[]` {
 518  		return nil
 519  	}
 520  
 521  	tmp := &struct {
 522  		CPUTime            *float64 `json:"CPU-TIME,omitempty" yaml:"cpu_timme,omitempty" structs:",omitempty"`
 523  		Write              *float64 `json:",omitempty" yaml:"write,omitempty" structs:",omitempty"`
 524  		Read               *float64 `json:",omitempty" yaml:"read,omitempty" structs:",omitempty"`
 525  		Receive            *float64 `json:",omitempty" yaml:"receive,omitempty" structs:",omitempty"`
 526  		Send               *float64 `json:",omitempty" yaml:"send,omitempty" structs:",omitempty"`
 527  		In                 *float64 `json:",omitempty" yaml:"in,omitempty" structs:",omitempty"`
 528  		Out                *float64 `json:",omitempty" yaml:"out,omitempty" structs:",omitempty"`
 529  		TotalMemorySize    *float64 `json:"Total-Memory-Size,omitempty" yaml:"total_memory_size,omitempty" structs:",omitempty"`
 530  		UsedMemorySize     *float64 `json:"Used-Memory-Size,omitempty" yaml:"used_memory_size,omitempty" structs:",omitempty"`
 531  		TotalDisk1Size     *float64 `json:"Total-Disk1-Size,omitempty" yaml:"total_disk1_size,omitempty" structs:",omitempty"`
 532  		UsedDisk1Size      *float64 `json:"Used-Disk1-Size,omitempty" yaml:"used_disk1_size,omitempty" structs:",omitempty"`
 533  		TotalDisk2Size     *float64 `json:"Total-Disk2-Size,omitempty" yaml:"total_disk2_size,omitempty" structs:",omitempty"`
 534  		UsedDisk2Size      *float64 `json:"Used-Disk2-Size,omitempty" yaml:"used_disk2_size,omitempty" structs:",omitempty"`
 535  		BinlogUsedSizeKiB  *float64 `json:"binlogUsedSizeKiB,omitempty" yaml:"binlog_used_size_kib,omitempty" structs:",omitempty"`
 536  		DelayTimeSec       *float64 `json:"delayTimeSec,omitempty" yaml:"delay_time_sec,omitempty" structs:",omitempty"`
 537  		FreeDiskSize       *float64 `json:"Free-Disk-Size,omitempty" yaml:"free_disk_size,omitempty" structs:",omitempty"`
 538  		ResponseTimeSec    *float64 `json:"responsetimesec,omitempty" yaml:"response_time_sec,omitempty" structs:",omitempty"`
 539  		UplinkBPS          *float64 `json:"UplinkBps,omitempty" yaml:"uplink_bps,omitempty" structs:",omitempty"`
 540  		DownlinkBPS        *float64 `json:"DownlinkBps,omitempty" yaml:"downlink_bps,omitempty" structs:",omitempty"`
 541  		ActiveConnections  *float64 `json:"activeConnections,omitempty" yaml:"active_connections,omitempty" structs:",omitempty"`
 542  		ConnectionsPerSec  *float64 `json:"connectionsPerSec,omitempty" yaml:"connections_per_sec,omitempty" structs:",omitempty"`
 543  		ReceiveBytesPerSec *float64 `json:"receiveBytesPerSec,omitempty" yaml:"receive_bytes_per_sec,omitempty" structs:",omitempty"`
 544  		SendBytesPerSec    *float64 `json:"sendBytesPerSec,omitempty" yaml:"send_bytes_per_sec,omitempty" structs:",omitempty"`
 545  	}{}
 546  	if err := json.Unmarshal(data, &tmp); err != nil {
 547  		return err
 548  	}
 549  
 550  	m.CPUTime = tmp.CPUTime
 551  	m.Write = tmp.Write
 552  	m.Read = tmp.Read
 553  	m.Receive = tmp.Receive
 554  	m.Send = tmp.Send
 555  	m.In = tmp.In
 556  	m.Out = tmp.Out
 557  	m.TotalMemorySize = tmp.TotalMemorySize
 558  	m.UsedMemorySize = tmp.UsedMemorySize
 559  	m.TotalDisk1Size = tmp.TotalDisk1Size
 560  	m.UsedDisk1Size = tmp.UsedDisk1Size
 561  	m.TotalDisk2Size = tmp.TotalDisk2Size
 562  	m.UsedDisk2Size = tmp.UsedDisk2Size
 563  	m.BinlogUsedSizeKiB = tmp.BinlogUsedSizeKiB
 564  	m.DelayTimeSec = tmp.DelayTimeSec
 565  	m.FreeDiskSize = tmp.FreeDiskSize
 566  	m.ResponseTimeSec = tmp.ResponseTimeSec
 567  	m.UplinkBPS = tmp.UplinkBPS
 568  	m.DownlinkBPS = tmp.DownlinkBPS
 569  	m.ActiveConnections = tmp.ActiveConnections
 570  	m.ConnectionsPerSec = tmp.ConnectionsPerSec
 571  	m.ReceiveBytesPerSec = tmp.ReceiveBytesPerSec
 572  	m.SendBytesPerSec = tmp.SendBytesPerSec
 573  
 574  	return nil
 575  }
 576  
 577  type rawMonitorValues map[string]*rawMonitorValue
 578  
 579  func (m *rawMonitorValues) monitorCPUTimeValues() (MonitorCPUTimeValues, error) {
 580  	var values MonitorCPUTimeValues
 581  
 582  	for k, v := range *m {
 583  		if v.CPUTime == nil {
 584  			continue
 585  		}
 586  		time, err := time.Parse(time.RFC3339, k) // RFC3339 ≒ ISO8601
 587  		if err != nil {
 588  			return nil, err
 589  		}
 590  		values = append(values, &MonitorCPUTimeValue{
 591  			Time:    time,
 592  			CPUTime: *v.CPUTime,
 593  		})
 594  	}
 595  
 596  	sort.Slice(values, func(i, j int) bool { return values[i].Time.Before(values[j].Time) })
 597  	return values, nil
 598  }
 599  
 600  func (m *rawMonitorValues) monitorDiskValues() (MonitorDiskValues, error) {
 601  	var values MonitorDiskValues
 602  
 603  	for k, v := range *m {
 604  		if v.Read == nil || v.Write == nil {
 605  			continue
 606  		}
 607  		time, err := time.Parse(time.RFC3339, k) // RFC3339 ≒ ISO8601
 608  		if err != nil {
 609  			return nil, err
 610  		}
 611  		values = append(values, &MonitorDiskValue{
 612  			Time:  time,
 613  			Read:  *v.Read,
 614  			Write: *v.Write,
 615  		})
 616  	}
 617  
 618  	sort.Slice(values, func(i, j int) bool { return values[i].Time.Before(values[j].Time) })
 619  	return values, nil
 620  }
 621  
 622  func (m *rawMonitorValues) monitorInterfaceValues() (MonitorInterfaceValues, error) {
 623  	var values MonitorInterfaceValues
 624  
 625  	for k, v := range *m {
 626  		if v.Send == nil || v.Receive == nil {
 627  			continue
 628  		}
 629  		time, err := time.Parse(time.RFC3339, k) // RFC3339 ≒ ISO8601
 630  		if err != nil {
 631  			return nil, err
 632  		}
 633  		values = append(values, &MonitorInterfaceValue{
 634  			Time:    time,
 635  			Send:    *v.Send,
 636  			Receive: *v.Receive,
 637  		})
 638  	}
 639  
 640  	sort.Slice(values, func(i, j int) bool { return values[i].Time.Before(values[j].Time) })
 641  	return values, nil
 642  }
 643  
 644  func (m *rawMonitorValues) monitorRouterValues() (MonitorRouterValues, error) {
 645  	var values MonitorRouterValues
 646  
 647  	for k, v := range *m {
 648  		if v.In == nil || v.Out == nil {
 649  			continue
 650  		}
 651  		time, err := time.Parse(time.RFC3339, k) // RFC3339 ≒ ISO8601
 652  		if err != nil {
 653  			return nil, err
 654  		}
 655  		values = append(values, &MonitorRouterValue{
 656  			Time: time,
 657  			In:   *v.In,
 658  			Out:  *v.Out,
 659  		})
 660  	}
 661  
 662  	sort.Slice(values, func(i, j int) bool { return values[i].Time.Before(values[j].Time) })
 663  	return values, nil
 664  }
 665  
 666  func (m *rawMonitorValues) monitorDatabaseValues() (MonitorDatabaseValues, error) {
 667  	var values MonitorDatabaseValues
 668  
 669  	for k, v := range *m {
 670  		if v.TotalMemorySize == nil || v.UsedMemorySize == nil ||
 671  			v.TotalDisk1Size == nil || v.UsedDisk1Size == nil ||
 672  			v.TotalDisk2Size == nil || v.UsedDisk2Size == nil {
 673  			continue
 674  		}
 675  		time, err := time.Parse(time.RFC3339, k) // RFC3339 ≒ ISO8601
 676  		if err != nil {
 677  			return nil, err
 678  		}
 679  		value := &MonitorDatabaseValue{
 680  			Time:            time,
 681  			TotalMemorySize: *v.TotalMemorySize,
 682  			UsedMemorySize:  *v.UsedMemorySize,
 683  			TotalDisk1Size:  *v.TotalDisk1Size,
 684  			UsedDisk1Size:   *v.UsedDisk1Size,
 685  			TotalDisk2Size:  *v.TotalDisk2Size,
 686  			UsedDisk2Size:   *v.UsedDisk2Size,
 687  		}
 688  		if v.BinlogUsedSizeKiB != nil {
 689  			value.BinlogUsedSizeKiB = *v.BinlogUsedSizeKiB
 690  		}
 691  		if v.DelayTimeSec != nil {
 692  			value.DelayTimeSec = *v.DelayTimeSec
 693  		}
 694  		values = append(values, value)
 695  	}
 696  
 697  	sort.Slice(values, func(i, j int) bool { return values[i].Time.Before(values[j].Time) })
 698  	return values, nil
 699  }
 700  
 701  func (m *rawMonitorValues) monitorFreeDiskSizeValues() (MonitorFreeDiskSizeValues, error) {
 702  	var values MonitorFreeDiskSizeValues
 703  
 704  	for k, v := range *m {
 705  		if v.FreeDiskSize == nil {
 706  			continue
 707  		}
 708  		time, err := time.Parse(time.RFC3339, k) // RFC3339 ≒ ISO8601
 709  		if err != nil {
 710  			return nil, err
 711  		}
 712  		values = append(values, &MonitorFreeDiskSizeValue{
 713  			Time:         time,
 714  			FreeDiskSize: *v.FreeDiskSize,
 715  		})
 716  	}
 717  
 718  	sort.Slice(values, func(i, j int) bool { return values[i].Time.Before(values[j].Time) })
 719  	return values, nil
 720  }
 721  
 722  func (m *rawMonitorValues) monitorResponseTimeSecValues() (MonitorResponseTimeSecValues, error) {
 723  	var values MonitorResponseTimeSecValues
 724  
 725  	for k, v := range *m {
 726  		if v.ResponseTimeSec == nil {
 727  			continue
 728  		}
 729  		time, err := time.Parse(time.RFC3339, k) // RFC3339 ≒ ISO8601
 730  		if err != nil {
 731  			return nil, err
 732  		}
 733  		values = append(values, &MonitorResponseTimeSecValue{
 734  			Time:            time,
 735  			ResponseTimeSec: *v.ResponseTimeSec,
 736  		})
 737  	}
 738  
 739  	sort.Slice(values, func(i, j int) bool { return values[i].Time.Before(values[j].Time) })
 740  	return values, nil
 741  }
 742  
 743  func (m *rawMonitorValues) monitorLinkValues() (MonitorLinkValues, error) {
 744  	var values MonitorLinkValues
 745  
 746  	for k, v := range *m {
 747  		if v.UplinkBPS == nil || v.DownlinkBPS == nil {
 748  			continue
 749  		}
 750  		time, err := time.Parse(time.RFC3339, k) // RFC3339 ≒ ISO8601
 751  		if err != nil {
 752  			return nil, err
 753  		}
 754  		values = append(values, &MonitorLinkValue{
 755  			Time:        time,
 756  			UplinkBPS:   *v.UplinkBPS,
 757  			DownlinkBPS: *v.DownlinkBPS,
 758  		})
 759  	}
 760  
 761  	sort.Slice(values, func(i, j int) bool { return values[i].Time.Before(values[j].Time) })
 762  	return values, nil
 763  }
 764  
 765  func (m *rawMonitorValues) monitorConnectionValues() (MonitorConnectionValues, error) {
 766  	var values MonitorConnectionValues
 767  
 768  	for k, v := range *m {
 769  		if v.ActiveConnections == nil || v.ConnectionsPerSec == nil {
 770  			continue
 771  		}
 772  		time, err := time.Parse(time.RFC3339, k) // RFC3339 ≒ ISO8601
 773  		if err != nil {
 774  			return nil, err
 775  		}
 776  		values = append(values, &MonitorConnectionValue{
 777  			Time:              time,
 778  			ActiveConnections: *v.ActiveConnections,
 779  			ConnectionsPerSec: *v.ConnectionsPerSec,
 780  		})
 781  	}
 782  
 783  	sort.Slice(values, func(i, j int) bool { return values[i].Time.Before(values[j].Time) })
 784  	return values, nil
 785  }
 786  
 787  func (m *rawMonitorValues) monitorLocalRouterValues() (MonitorLocalRouterValues, error) {
 788  	var values MonitorLocalRouterValues
 789  
 790  	for k, v := range *m {
 791  		if v.ReceiveBytesPerSec == nil || v.SendBytesPerSec == nil {
 792  			continue
 793  		}
 794  		time, err := time.Parse(time.RFC3339, k) // RFC3339 ≒ ISO8601
 795  		if err != nil {
 796  			return nil, err
 797  		}
 798  		values = append(values, &MonitorLocalRouterValue{
 799  			Time:               time,
 800  			ReceiveBytesPerSec: *v.ReceiveBytesPerSec,
 801  			SendBytesPerSec:    *v.SendBytesPerSec,
 802  		})
 803  	}
 804  
 805  	sort.Slice(values, func(i, j int) bool { return values[i].Time.Before(values[j].Time) })
 806  	return values, nil
 807  }
 808