Merged with master, resolved conflicts
This commit is contained in:
+8
-4
@@ -13,7 +13,7 @@ func Register(r *macaron.Macaron) {
|
||||
reqSignedIn := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true})
|
||||
reqGrafanaAdmin := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true, ReqGrafanaAdmin: true})
|
||||
reqEditorRole := middleware.RoleAuth(m.ROLE_EDITOR, m.ROLE_ADMIN)
|
||||
regOrgAdmin := middleware.RoleAuth(m.ROLE_ADMIN)
|
||||
reqOrgAdmin := middleware.RoleAuth(m.ROLE_ADMIN)
|
||||
quota := middleware.Quota
|
||||
bind := binding.Bind
|
||||
|
||||
@@ -41,6 +41,9 @@ func Register(r *macaron.Macaron) {
|
||||
r.Get("/admin/orgs", reqGrafanaAdmin, Index)
|
||||
r.Get("/admin/orgs/edit/:id", reqGrafanaAdmin, Index)
|
||||
|
||||
r.Get("/plugins", reqSignedIn, Index)
|
||||
r.Get("/plugins/edit/*", reqSignedIn, Index)
|
||||
|
||||
r.Get("/dashboard/*", reqSignedIn, Index)
|
||||
r.Get("/dashboard-solo/*", reqSignedIn, Index)
|
||||
|
||||
@@ -65,6 +68,7 @@ func Register(r *macaron.Macaron) {
|
||||
r.Post("/api/snapshots/", bind(m.CreateDashboardSnapshotCommand{}), CreateDashboardSnapshot)
|
||||
r.Get("/dashboard/snapshot/*", Index)
|
||||
|
||||
r.Get("/api/snapshot/shared-options/", GetSharingOptions)
|
||||
r.Get("/api/snapshots/:key", GetDashboardSnapshot)
|
||||
r.Get("/api/snapshots-delete/:key", DeleteDashboardSnapshot)
|
||||
|
||||
@@ -113,7 +117,7 @@ func Register(r *macaron.Macaron) {
|
||||
r.Get("/invites", wrap(GetPendingOrgInvites))
|
||||
r.Post("/invites", quota("user"), bind(dtos.AddInviteForm{}), wrap(AddOrgInvite))
|
||||
r.Patch("/invites/:code/revoke", wrap(RevokeInvite))
|
||||
}, regOrgAdmin)
|
||||
}, reqOrgAdmin)
|
||||
|
||||
// create new org
|
||||
r.Post("/orgs", quota("org"), bind(m.CreateOrgCommand{}), wrap(CreateOrg))
|
||||
@@ -140,7 +144,7 @@ func Register(r *macaron.Macaron) {
|
||||
r.Get("/", wrap(GetApiKeys))
|
||||
r.Post("/", quota("api_key"), bind(m.AddApiKeyCommand{}), wrap(AddApiKey))
|
||||
r.Delete("/:id", wrap(DeleteApiKey))
|
||||
}, regOrgAdmin)
|
||||
}, reqOrgAdmin)
|
||||
|
||||
// Data sources
|
||||
r.Group("/datasources", func() {
|
||||
@@ -150,7 +154,7 @@ func Register(r *macaron.Macaron) {
|
||||
r.Delete("/:id", DeleteDataSource)
|
||||
r.Get("/:id", wrap(GetDataSourceById))
|
||||
r.Get("/plugins", GetDataSourcePlugins)
|
||||
}, regOrgAdmin)
|
||||
}, reqOrgAdmin)
|
||||
|
||||
r.Get("/frontend/settings/", GetFrontendSettings)
|
||||
r.Any("/datasources/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
|
||||
"github.com/aws/aws-sdk-go/aws/ec2metadata"
|
||||
@@ -30,13 +31,15 @@ type cwRequest struct {
|
||||
|
||||
func init() {
|
||||
actionHandlers = map[string]actionHandler{
|
||||
"GetMetricStatistics": handleGetMetricStatistics,
|
||||
"ListMetrics": handleListMetrics,
|
||||
"DescribeInstances": handleDescribeInstances,
|
||||
"__GetRegions": handleGetRegions,
|
||||
"__GetNamespaces": handleGetNamespaces,
|
||||
"__GetMetrics": handleGetMetrics,
|
||||
"__GetDimensions": handleGetDimensions,
|
||||
"GetMetricStatistics": handleGetMetricStatistics,
|
||||
"ListMetrics": handleListMetrics,
|
||||
"DescribeAlarmsForMetric": handleDescribeAlarmsForMetric,
|
||||
"DescribeAlarmHistory": handleDescribeAlarmHistory,
|
||||
"DescribeInstances": handleDescribeInstances,
|
||||
"__GetRegions": handleGetRegions,
|
||||
"__GetNamespaces": handleGetNamespaces,
|
||||
"__GetMetrics": handleGetMetrics,
|
||||
"__GetDimensions": handleGetDimensions,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +122,107 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) {
|
||||
Dimensions: reqParam.Parameters.Dimensions,
|
||||
}
|
||||
|
||||
resp, err := svc.ListMetrics(params)
|
||||
var resp cloudwatch.ListMetricsOutput
|
||||
err := svc.ListMetricsPages(params,
|
||||
func(page *cloudwatch.ListMetricsOutput, lastPage bool) bool {
|
||||
metrics, _ := awsutil.ValuesAtPath(page, "Metrics")
|
||||
for _, metric := range metrics {
|
||||
resp.Metrics = append(resp.Metrics, metric.(*cloudwatch.Metric))
|
||||
}
|
||||
return !lastPage
|
||||
})
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, "Unable to call AWS API", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, resp)
|
||||
}
|
||||
|
||||
func handleDescribeAlarmsForMetric(req *cwRequest, c *middleware.Context) {
|
||||
sess := session.New()
|
||||
creds := credentials.NewChainCredentials(
|
||||
[]credentials.Provider{
|
||||
&credentials.EnvProvider{},
|
||||
&credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database},
|
||||
&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute},
|
||||
})
|
||||
|
||||
cfg := &aws.Config{
|
||||
Region: aws.String(req.Region),
|
||||
Credentials: creds,
|
||||
}
|
||||
|
||||
svc := cloudwatch.New(session.New(cfg), cfg)
|
||||
|
||||
reqParam := &struct {
|
||||
Parameters struct {
|
||||
Namespace string `json:"namespace"`
|
||||
MetricName string `json:"metricName"`
|
||||
Dimensions []*cloudwatch.Dimension `json:"dimensions"`
|
||||
Statistic string `json:"statistic"`
|
||||
Period int64 `json:"period"`
|
||||
} `json:"parameters"`
|
||||
}{}
|
||||
json.Unmarshal(req.Body, reqParam)
|
||||
|
||||
params := &cloudwatch.DescribeAlarmsForMetricInput{
|
||||
Namespace: aws.String(reqParam.Parameters.Namespace),
|
||||
MetricName: aws.String(reqParam.Parameters.MetricName),
|
||||
Period: aws.Int64(reqParam.Parameters.Period),
|
||||
}
|
||||
if len(reqParam.Parameters.Dimensions) != 0 {
|
||||
params.Dimensions = reqParam.Parameters.Dimensions
|
||||
}
|
||||
if reqParam.Parameters.Statistic != "" {
|
||||
params.Statistic = aws.String(reqParam.Parameters.Statistic)
|
||||
}
|
||||
|
||||
resp, err := svc.DescribeAlarmsForMetric(params)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, "Unable to call AWS API", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, resp)
|
||||
}
|
||||
|
||||
func handleDescribeAlarmHistory(req *cwRequest, c *middleware.Context) {
|
||||
sess := session.New()
|
||||
creds := credentials.NewChainCredentials(
|
||||
[]credentials.Provider{
|
||||
&credentials.EnvProvider{},
|
||||
&credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database},
|
||||
&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(sess), ExpiryWindow: 5 * time.Minute},
|
||||
})
|
||||
|
||||
cfg := &aws.Config{
|
||||
Region: aws.String(req.Region),
|
||||
Credentials: creds,
|
||||
}
|
||||
|
||||
svc := cloudwatch.New(session.New(cfg), cfg)
|
||||
|
||||
reqParam := &struct {
|
||||
Parameters struct {
|
||||
AlarmName string `json:"alarmName"`
|
||||
HistoryItemType string `json:"historyItemType"`
|
||||
StartDate int64 `json:"startDate"`
|
||||
EndDate int64 `json:"endDate"`
|
||||
} `json:"parameters"`
|
||||
}{}
|
||||
json.Unmarshal(req.Body, reqParam)
|
||||
|
||||
params := &cloudwatch.DescribeAlarmHistoryInput{
|
||||
AlarmName: aws.String(reqParam.Parameters.AlarmName),
|
||||
StartDate: aws.Time(time.Unix(reqParam.Parameters.StartDate, 0)),
|
||||
EndDate: aws.Time(time.Unix(reqParam.Parameters.EndDate, 0)),
|
||||
}
|
||||
if reqParam.Parameters.HistoryItemType != "" {
|
||||
params.HistoryItemType = aws.String(reqParam.Parameters.HistoryItemType)
|
||||
}
|
||||
|
||||
resp, err := svc.DescribeAlarmHistory(params)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, "Unable to call AWS API", err)
|
||||
return
|
||||
@@ -160,7 +263,15 @@ func handleDescribeInstances(req *cwRequest, c *middleware.Context) {
|
||||
params.InstanceIds = reqParam.Parameters.InstanceIds
|
||||
}
|
||||
|
||||
resp, err := svc.DescribeInstances(params)
|
||||
var resp ec2.DescribeInstancesOutput
|
||||
err := svc.DescribeInstancesPages(params,
|
||||
func(page *ec2.DescribeInstancesOutput, lastPage bool) bool {
|
||||
reservations, _ := awsutil.ValuesAtPath(page, "Reservations")
|
||||
for _, reservation := range reservations {
|
||||
resp.Reservations = append(resp.Reservations, reservation.(*ec2.Reservation))
|
||||
}
|
||||
return !lastPage
|
||||
})
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, "Unable to call AWS API", err)
|
||||
return
|
||||
|
||||
@@ -15,31 +15,47 @@ func init() {
|
||||
metricsMap = map[string][]string{
|
||||
"AWS/AutoScaling": {"GroupMinSize", "GroupMaxSize", "GroupDesiredCapacity", "GroupInServiceInstances", "GroupPendingInstances", "GroupStandbyInstances", "GroupTerminatingInstances", "GroupTotalInstances"},
|
||||
"AWS/Billing": {"EstimatedCharges"},
|
||||
"AWS/EC2": {"CPUCreditUsage", "CPUCreditBalance", "CPUUtilization", "DiskReadOps", "DiskWriteOps", "DiskReadBytes", "DiskWriteBytes", "NetworkIn", "NetworkOut", "StatusCheckFailed", "StatusCheckFailed_Instance", "StatusCheckFailed_System"},
|
||||
"AWS/ECS": {"CPUUtilization", "MemoryUtilization"},
|
||||
"AWS/CloudFront": {"Requests", "BytesDownloaded", "BytesUploaded", "TotalErrorRate", "4xxErrorRate", "5xxErrorRate"},
|
||||
"AWS/CloudSearch": {"SuccessfulRequests", "SearchableDocuments", "IndexUtilization", "Partitions"},
|
||||
"AWS/DynamoDB": {"ConditionalCheckFailedRequests", "ConsumedReadCapacityUnits", "ConsumedWriteCapacityUnits", "OnlineIndexConsumedWriteCapacity", "OnlineIndexPercentageProgress", "OnlineIndexThrottleEvents", "ProvisionedReadCapacityUnits", "ProvisionedWriteCapacityUnits", "ReadThrottleEvents", "ReturnedItemCount", "SuccessfulRequestLatency", "SystemErrors", "ThrottledRequests", "UserErrors", "WriteThrottleEvents"},
|
||||
"AWS/ECS": {"CPUUtilization", "MemoryUtilization"},
|
||||
"AWS/ElastiCache": {
|
||||
"CPUUtilization", "SwapUsage", "FreeableMemory", "NetworkBytesIn", "NetworkBytesOut",
|
||||
"CPUUtilization", "FreeableMemory", "NetworkBytesIn", "NetworkBytesOut", "SwapUsage",
|
||||
"BytesUsedForCacheItems", "BytesReadIntoMemcached", "BytesWrittenOutFromMemcached", "CasBadval", "CasHits", "CasMisses", "CmdFlush", "CmdGet", "CmdSet", "CurrConnections", "CurrItems", "DecrHits", "DecrMisses", "DeleteHits", "DeleteMisses", "Evictions", "GetHits", "GetMisses", "IncrHits", "IncrMisses", "Reclaimed",
|
||||
"CurrConnections", "Evictions", "Reclaimed", "NewConnections", "BytesUsedForCache", "CacheHits", "CacheMisses", "ReplicationLag", "GetTypeCmds", "SetTypeCmds", "KeyBasedCmds", "StringBasedCmds", "HashBasedCmds", "ListBasedCmds", "SetBasedCmds", "SortedSetBasedCmds", "CurrItems",
|
||||
"BytesUsedForHash", "CmdConfigGet", "CmdConfigSet", "CmdTouch", "CurrConfig", "EvictedUnfetched", "ExpiredUnfetched", "SlabsMoved", "TouchHits", "TouchMisses",
|
||||
"NewConnections", "NewItems", "UnusedMemory",
|
||||
"BytesUsedForCache", "CacheHits", "CacheMisses", "CurrConnections", "Evictions", "HyperLogLogBasedCmds", "NewConnections", "Reclaimed", "ReplicationBytes", "ReplicationLag", "SaveInProgress",
|
||||
"CurrItems", "GetTypeCmds", "HashBasedCmds", "KeyBasedCmds", "ListBasedCmds", "SetBasedCmds", "SetTypeCmds", "SortedSetBasedCmds", "StringBasedCmds",
|
||||
},
|
||||
"AWS/EBS": {"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps"},
|
||||
"AWS/ELB": {"HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount"},
|
||||
"AWS/ElasticMapReduce": {"CoreNodesPending", "CoreNodesRunning", "HBaseBackupFailed", "HBaseMostRecentBackupDuration", "HBaseTimeSinceLastSuccessfulBackup", "HDFSBytesRead", "HDFSBytesWritten", "HDFSUtilization", "IsIdle", "JobsFailed", "JobsRunning", "LiveDataNodes", "LiveTaskTrackers", "MapSlotsOpen", "MissingBlocks", "ReduceSlotsOpen", "RemainingMapTasks", "RemainingMapTasksPerSlot", "RemainingReduceTasks", "RunningMapTasks", "RunningReduceTasks", "S3BytesRead", "S3BytesWritten", "TaskNodesPending", "TaskNodesRunning", "TotalLoad"},
|
||||
"AWS/Kinesis": {"PutRecord.Bytes", "PutRecord.Latency", "PutRecord.Success", "PutRecords.Bytes", "PutRecords.Latency", "PutRecords.Records", "PutRecords.Success", "IncomingBytes", "IncomingRecords", "GetRecords.Bytes", "GetRecords.IteratorAgeMilliseconds", "GetRecords.Latency", "GetRecords.Success"},
|
||||
"AWS/ML": {"PredictCount", "PredictFailureCount"},
|
||||
"AWS/OpsWorks": {"cpu_idle", "cpu_nice", "cpu_system", "cpu_user", "cpu_waitio", "load_1", "load_5", "load_15", "memory_buffers", "memory_cached", "memory_free", "memory_swap", "memory_total", "memory_used", "procs"},
|
||||
"AWS/Redshift": {"CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"},
|
||||
"AWS/RDS": {"BinLogDiskUsage", "CPUUtilization", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"},
|
||||
"AWS/Route53": {"HealthCheckStatus", "HealthCheckPercentageHealthy"},
|
||||
"AWS/SNS": {"NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"},
|
||||
"AWS/SQS": {"NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"},
|
||||
"AWS/S3": {"BucketSizeBytes", "NumberOfObjects"},
|
||||
"AWS/SWF": {"DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut"},
|
||||
"AWS/StorageGateway": {"CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "CloudBytesDownloaded", "CloudDownloadLatency", "CloudBytesUploaded", "UploadBufferFree", "UploadBufferPercentUsed", "UploadBufferUsed", "QueuedWrites", "ReadBytes", "ReadTime", "TotalCacheSize", "WriteBytes", "WriteTime", "WorkingStorageFree", "WorkingStoragePercentUsed", "WorkingStorageUsed", "CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "ReadBytes", "ReadTime", "WriteBytes", "WriteTime", "QueuedWrites"},
|
||||
"AWS/WorkSpaces": {"Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"},
|
||||
"AWS/EBS": {"VolumeReadBytes", "VolumeWriteBytes", "VolumeReadOps", "VolumeWriteOps", "VolumeTotalReadTime", "VolumeTotalWriteTime", "VolumeIdleTime", "VolumeQueueLength", "VolumeThroughputPercentage", "VolumeConsumedReadWriteOps"},
|
||||
"AWS/EC2": {"CPUCreditUsage", "CPUCreditBalance", "CPUUtilization", "DiskReadOps", "DiskWriteOps", "DiskReadBytes", "DiskWriteBytes", "NetworkIn", "NetworkOut", "StatusCheckFailed", "StatusCheckFailed_Instance", "StatusCheckFailed_System"},
|
||||
"AWS/ELB": {"HealthyHostCount", "UnHealthyHostCount", "RequestCount", "Latency", "HTTPCode_ELB_4XX", "HTTPCode_ELB_5XX", "HTTPCode_Backend_2XX", "HTTPCode_Backend_3XX", "HTTPCode_Backend_4XX", "HTTPCode_Backend_5XX", "BackendConnectionErrors", "SurgeQueueLength", "SpilloverCount"},
|
||||
"AWS/ElasticMapReduce": {"IsIdle", "JobsRunning", "JobsFailed",
|
||||
"MapTasksRunning", "MapTasksRemaining", "MapSlotsOpen", "RemainingMapTasksPerSlot", "ReduceTasksRunning", "ReduceTasksRemaining", "ReduceSlotsOpen",
|
||||
"CoreNodesRunning", "CoreNodesPending", "LiveDataNodes", "TaskNodesRunning", "TaskNodesPending", "LiveTaskTrackers",
|
||||
"S3BytesWritten", "S3BytesRead", "HDFSUtilization", "HDFSBytesRead", "HDFSBytesWritten", "MissingBlocks", "TotalLoad",
|
||||
"BackupFailed", "MostRecentBackupDuration", "TimeSinceLastSuccessfulBackup",
|
||||
"IsIdle", "ContainerAllocated", "ContainerReserved", "ContainerPending", "AppsCompleted", "AppsFailed", "AppsKilled", "AppsPending", "AppsRunning", "AppsSubmitted",
|
||||
"CoreNodesRunning", "CoreNodesPending", "LiveDataNodes", "MRTotalNodes", "MRActiveNodes", "MRLostNodes", "MRUnhealthyNodes", "MRDecommissionedNodes", "MRRebootedNodes",
|
||||
"S3BytesWritten", "S3BytesRead", "HDFSUtilization", "HDFSBytesRead", "HDFSBytesWritten", "MissingBlocks", "CorruptBlocks", "TotalLoad", "MemoryTotalMB", "MemoryReservedMB", "MemoryAvailableMB", "MemoryAllocatedMB", "PendingDeletionBlocks", "UnderReplicatedBlocks", "DfsPendingReplicationBlocks", "CapacityRemainingGB",
|
||||
"HbaseBackupFailed", "MostRecentBackupDuration", "TimeSinceLastSuccessfulBackup"},
|
||||
"AWS/ES": {"ClusterStatus.green", "ClusterStatus.yellow", "ClusterStatus.red", "Nodes", "SearchableDocuments", "DeletedDocuments", "CPUUtilization", "FreeStorageSpace", "JVMMemoryPressure", "AutomatedSnapshotFailure", "MasterCPUUtilization", "MasterFreeStorageSpace", "MasterJVMMemoryPressure", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "DiskQueueLength", "ReadIOPS", "WriteIOPS"},
|
||||
"AWS/Kinesis": {"PutRecord.Bytes", "PutRecord.Latency", "PutRecord.Success", "PutRecords.Bytes", "PutRecords.Latency", "PutRecords.Records", "PutRecords.Success", "IncomingBytes", "IncomingRecords", "GetRecords.Bytes", "GetRecords.IteratorAgeMilliseconds", "GetRecords.Latency", "GetRecords.Success"},
|
||||
"AWS/Lambda": {"Invocations", "Errors", "Duration", "Throttles"},
|
||||
"AWS/ML": {"PredictCount", "PredictFailureCount"},
|
||||
"AWS/OpsWorks": {"cpu_idle", "cpu_nice", "cpu_system", "cpu_user", "cpu_waitio", "load_1", "load_5", "load_15", "memory_buffers", "memory_cached", "memory_free", "memory_swap", "memory_total", "memory_used", "procs"},
|
||||
"AWS/Redshift": {"CPUUtilization", "DatabaseConnections", "HealthStatus", "MaintenanceMode", "NetworkReceiveThroughput", "NetworkTransmitThroughput", "PercentageDiskSpaceUsed", "ReadIOPS", "ReadLatency", "ReadThroughput", "WriteIOPS", "WriteLatency", "WriteThroughput"},
|
||||
"AWS/RDS": {"BinLogDiskUsage", "CPUUtilization", "CPUCreditUsage", "CPUCreditBalance", "DatabaseConnections", "DiskQueueDepth", "FreeableMemory", "FreeStorageSpace", "ReplicaLag", "SwapUsage", "ReadIOPS", "WriteIOPS", "ReadLatency", "WriteLatency", "ReadThroughput", "WriteThroughput", "NetworkReceiveThroughput", "NetworkTransmitThroughput"},
|
||||
"AWS/Route53": {"HealthCheckStatus", "HealthCheckPercentageHealthy"},
|
||||
"AWS/SNS": {"NumberOfMessagesPublished", "PublishSize", "NumberOfNotificationsDelivered", "NumberOfNotificationsFailed"},
|
||||
"AWS/SQS": {"NumberOfMessagesSent", "SentMessageSize", "NumberOfMessagesReceived", "NumberOfEmptyReceives", "NumberOfMessagesDeleted", "ApproximateNumberOfMessagesDelayed", "ApproximateNumberOfMessagesVisible", "ApproximateNumberOfMessagesNotVisible"},
|
||||
"AWS/S3": {"BucketSizeBytes", "NumberOfObjects"},
|
||||
"AWS/SWF": {"DecisionTaskScheduleToStartTime", "DecisionTaskStartToCloseTime", "DecisionTasksCompleted", "StartedDecisionTasksTimedOutOnClose", "WorkflowStartToCloseTime", "WorkflowsCanceled", "WorkflowsCompleted", "WorkflowsContinuedAsNew", "WorkflowsFailed", "WorkflowsTerminated", "WorkflowsTimedOut",
|
||||
"ActivityTaskScheduleToCloseTime", "ActivityTaskScheduleToStartTime", "ActivityTaskStartToCloseTime", "ActivityTasksCanceled", "ActivityTasksCompleted", "ActivityTasksFailed", "ScheduledActivityTasksTimedOutOnClose", "ScheduledActivityTasksTimedOutOnStart", "StartedActivityTasksTimedOutOnClose", "StartedActivityTasksTimedOutOnHeartbeat"},
|
||||
"AWS/StorageGateway": {"CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "CloudBytesDownloaded", "CloudDownloadLatency", "CloudBytesUploaded", "UploadBufferFree", "UploadBufferPercentUsed", "UploadBufferUsed", "QueuedWrites", "ReadBytes", "ReadTime", "TotalCacheSize", "WriteBytes", "WriteTime", "TimeSinceLastRecoveryPoint", "WorkingStorageFree", "WorkingStoragePercentUsed", "WorkingStorageUsed",
|
||||
"CacheHitPercent", "CachePercentUsed", "CachePercentDirty", "ReadBytes", "ReadTime", "WriteBytes", "WriteTime", "QueuedWrites"},
|
||||
"AWS/WAF": {"AllowedRequests", "BlockedRequests", "CountedRequests"},
|
||||
"AWS/WorkSpaces": {"Available", "Unhealthy", "ConnectionAttempt", "ConnectionSuccess", "ConnectionFailure", "SessionLaunchTime", "InSessionLatency", "SessionDisconnect"},
|
||||
}
|
||||
dimensionsMap = map[string][]string{
|
||||
"AWS/AutoScaling": {"AutoScalingGroupName"},
|
||||
@@ -47,13 +63,15 @@ func init() {
|
||||
"AWS/CloudFront": {"DistributionId", "Region"},
|
||||
"AWS/CloudSearch": {},
|
||||
"AWS/DynamoDB": {"TableName", "GlobalSecondaryIndexName", "Operation"},
|
||||
"AWS/ECS": {"ClusterName", "ServiceName"},
|
||||
"AWS/ElastiCache": {"CacheClusterId", "CacheNodeId"},
|
||||
"AWS/EBS": {"VolumeId"},
|
||||
"AWS/EC2": {"AutoScalingGroupName", "ImageId", "InstanceId", "InstanceType"},
|
||||
"AWS/ECS": {"ClusterName", "ServiceName"},
|
||||
"AWS/ELB": {"LoadBalancerName", "AvailabilityZone"},
|
||||
"AWS/ElasticMapReduce": {"ClusterId", "JobId"},
|
||||
"AWS/ElasticMapReduce": {"ClusterId", "JobFlowId", "JobId"},
|
||||
"AWS/ES": {},
|
||||
"AWS/Kinesis": {"StreamName"},
|
||||
"AWS/Lambda": {"FunctionName"},
|
||||
"AWS/ML": {"MLModelId", "RequestMode"},
|
||||
"AWS/OpsWorks": {"StackId", "LayerId", "InstanceId"},
|
||||
"AWS/Redshift": {"NodeID", "ClusterIdentifier"},
|
||||
@@ -62,8 +80,9 @@ func init() {
|
||||
"AWS/SNS": {"Application", "Platform", "TopicName"},
|
||||
"AWS/SQS": {"QueueName"},
|
||||
"AWS/S3": {"BucketName", "StorageType"},
|
||||
"AWS/SWF": {"Domain", "ActivityTypeName", "ActivityTypeVersion"},
|
||||
"AWS/SWF": {"Domain", "WorkflowTypeName", "WorkflowTypeVersion", "ActivityTypeName", "ActivityTypeVersion"},
|
||||
"AWS/StorageGateway": {"GatewayId", "GatewayName", "VolumeId"},
|
||||
"AWS/WAF": {"Rule", "WebACL"},
|
||||
"AWS/WorkSpaces": {"DirectoryId", "WorkspaceId"},
|
||||
}
|
||||
}
|
||||
@@ -113,6 +132,7 @@ func handleGetMetrics(req *cwRequest, c *middleware.Context) {
|
||||
c.JsonApiErr(404, "Unable to find namespace "+reqParam.Parameters.Namespace, nil)
|
||||
return
|
||||
}
|
||||
sort.Sort(sort.StringSlice(namespaceMetrics))
|
||||
|
||||
result := []interface{}{}
|
||||
for _, name := range namespaceMetrics {
|
||||
@@ -136,6 +156,7 @@ func handleGetDimensions(req *cwRequest, c *middleware.Context) {
|
||||
c.JsonApiErr(404, "Unable to find dimension "+reqParam.Parameters.Namespace, nil)
|
||||
return
|
||||
}
|
||||
sort.Sort(sort.StringSlice(dimensionValues))
|
||||
|
||||
result := []interface{}{}
|
||||
for _, name := range dimensionValues {
|
||||
|
||||
@@ -12,6 +12,14 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func GetSharingOptions(c *middleware.Context) {
|
||||
c.JSON(200, util.DynMap{
|
||||
"externalSnapshotURL": setting.ExternalSnapshotUrl,
|
||||
"externalSnapshotName": setting.ExternalSnapshotName,
|
||||
"externalEnabled": setting.ExternalEnabled,
|
||||
})
|
||||
}
|
||||
|
||||
func CreateDashboardSnapshot(c *middleware.Context, cmd m.CreateDashboardSnapshotCommand) {
|
||||
if cmd.External {
|
||||
// external snapshot ref requires key and delete key
|
||||
|
||||
@@ -65,6 +65,7 @@ func GetDataSourceById(c *middleware.Context) Response {
|
||||
BasicAuth: ds.BasicAuth,
|
||||
BasicAuthUser: ds.BasicAuthUser,
|
||||
BasicAuthPassword: ds.BasicAuthPassword,
|
||||
WithCredentials: ds.WithCredentials,
|
||||
IsDefault: ds.IsDefault,
|
||||
JsonData: ds.JsonData,
|
||||
})
|
||||
@@ -117,7 +118,7 @@ func GetDataSourcePlugins(c *middleware.Context) {
|
||||
dsList := make(map[string]interface{})
|
||||
|
||||
for key, value := range plugins.DataSources {
|
||||
if value.(map[string]interface{})["builtIn"] == nil {
|
||||
if !value.BuiltIn {
|
||||
dsList[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package dtos
|
||||
|
||||
type IndexViewData struct {
|
||||
User *CurrentUser
|
||||
Settings map[string]interface{}
|
||||
AppUrl string
|
||||
AppSubUrl string
|
||||
GoogleAnalyticsId string
|
||||
GoogleTagManagerId string
|
||||
|
||||
PluginCss []*PluginCss
|
||||
PluginJs []string
|
||||
MainNavLinks []*NavLink
|
||||
}
|
||||
|
||||
type PluginCss struct {
|
||||
Light string `json:"light"`
|
||||
Dark string `json:"dark"`
|
||||
}
|
||||
|
||||
type NavLink struct {
|
||||
Text string `json:"text"`
|
||||
Icon string `json:"icon"`
|
||||
Href string `json:"href"`
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package dtos
|
||||
|
||||
type PluginBundle struct {
|
||||
Type string `json:"type"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Module string `json:"module"`
|
||||
JsonData map[string]interface{} `json:"jsonData"`
|
||||
}
|
||||
@@ -62,6 +62,9 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
|
||||
if ds.BasicAuth {
|
||||
dsMap["basicAuth"] = util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword)
|
||||
}
|
||||
if ds.WithCredentials {
|
||||
dsMap["withCredentials"] = ds.WithCredentials
|
||||
}
|
||||
|
||||
if ds.Type == m.DS_INFLUXDB_08 {
|
||||
dsMap["username"] = ds.User
|
||||
@@ -106,11 +109,21 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
|
||||
defaultDatasource = "-- Grafana --"
|
||||
}
|
||||
|
||||
panels := map[string]interface{}{}
|
||||
for _, panel := range plugins.Panels {
|
||||
panels[panel.Type] = map[string]interface{}{
|
||||
"module": panel.Module,
|
||||
"name": panel.Name,
|
||||
}
|
||||
}
|
||||
|
||||
jsonObj := map[string]interface{}{
|
||||
"defaultDatasource": defaultDatasource,
|
||||
"datasources": datasources,
|
||||
"panels": panels,
|
||||
"appSubUrl": setting.AppSubUrl,
|
||||
"allowOrgCreate": (setting.AllowUserOrgCreate && c.IsSignedIn) || c.IsGrafanaAdmin,
|
||||
"authProxyEnabled": setting.AuthProxyEnabled,
|
||||
"buildInfo": map[string]interface{}{
|
||||
"version": setting.BuildVersion,
|
||||
"commit": setting.BuildCommit,
|
||||
|
||||
+44
-35
@@ -3,65 +3,74 @@ package api
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func setIndexViewData(c *middleware.Context) error {
|
||||
func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
|
||||
settings, err := getFrontendSettingsMap(c)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
currentUser := &dtos.CurrentUser{
|
||||
Id: c.UserId,
|
||||
IsSignedIn: c.IsSignedIn,
|
||||
Login: c.Login,
|
||||
Email: c.Email,
|
||||
Name: c.Name,
|
||||
LightTheme: c.Theme == "light",
|
||||
OrgId: c.OrgId,
|
||||
OrgName: c.OrgName,
|
||||
OrgRole: c.OrgRole,
|
||||
GravatarUrl: dtos.GetGravatarUrl(c.Email),
|
||||
IsGrafanaAdmin: c.IsGrafanaAdmin,
|
||||
var data = dtos.IndexViewData{
|
||||
User: &dtos.CurrentUser{
|
||||
Id: c.UserId,
|
||||
IsSignedIn: c.IsSignedIn,
|
||||
Login: c.Login,
|
||||
Email: c.Email,
|
||||
Name: c.Name,
|
||||
LightTheme: c.Theme == "light",
|
||||
OrgId: c.OrgId,
|
||||
OrgName: c.OrgName,
|
||||
OrgRole: c.OrgRole,
|
||||
GravatarUrl: dtos.GetGravatarUrl(c.Email),
|
||||
IsGrafanaAdmin: c.IsGrafanaAdmin,
|
||||
},
|
||||
Settings: settings,
|
||||
AppUrl: setting.AppUrl,
|
||||
AppSubUrl: setting.AppSubUrl,
|
||||
GoogleAnalyticsId: setting.GoogleAnalyticsId,
|
||||
GoogleTagManagerId: setting.GoogleTagManagerId,
|
||||
}
|
||||
|
||||
if setting.DisableGravatar {
|
||||
currentUser.GravatarUrl = setting.AppSubUrl + "/img/user_profile.png"
|
||||
data.User.GravatarUrl = setting.AppSubUrl + "/img/user_profile.png"
|
||||
}
|
||||
|
||||
if len(currentUser.Name) == 0 {
|
||||
currentUser.Name = currentUser.Login
|
||||
if len(data.User.Name) == 0 {
|
||||
data.User.Name = data.User.Login
|
||||
}
|
||||
|
||||
themeUrlParam := c.Query("theme")
|
||||
if themeUrlParam == "light" {
|
||||
currentUser.LightTheme = true
|
||||
data.User.LightTheme = true
|
||||
}
|
||||
|
||||
c.Data["User"] = currentUser
|
||||
c.Data["Settings"] = settings
|
||||
c.Data["AppUrl"] = setting.AppUrl
|
||||
c.Data["AppSubUrl"] = setting.AppSubUrl
|
||||
data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{
|
||||
Text: "Dashboards",
|
||||
Icon: "fa fa-fw fa-th-large",
|
||||
Href: "/",
|
||||
})
|
||||
|
||||
if setting.GoogleAnalyticsId != "" {
|
||||
c.Data["GoogleAnalyticsId"] = setting.GoogleAnalyticsId
|
||||
if c.OrgRole == m.ROLE_ADMIN {
|
||||
data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{
|
||||
Text: "Data Sources",
|
||||
Icon: "fa fa-fw fa-database",
|
||||
Href: "/datasources",
|
||||
})
|
||||
}
|
||||
|
||||
if setting.GoogleTagManagerId != "" {
|
||||
c.Data["GoogleTagManagerId"] = setting.GoogleTagManagerId
|
||||
}
|
||||
|
||||
return nil
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func Index(c *middleware.Context) {
|
||||
if err := setIndexViewData(c); err != nil {
|
||||
if data, err := setIndexViewData(c); err != nil {
|
||||
c.Handle(500, "Failed to get settings", err)
|
||||
return
|
||||
} else {
|
||||
c.HTML(200, "index", data)
|
||||
}
|
||||
|
||||
c.HTML(200, "index")
|
||||
}
|
||||
|
||||
func NotFoundHandler(c *middleware.Context) {
|
||||
@@ -70,10 +79,10 @@ func NotFoundHandler(c *middleware.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := setIndexViewData(c); err != nil {
|
||||
if data, err := setIndexViewData(c); err != nil {
|
||||
c.Handle(500, "Failed to get settings", err)
|
||||
return
|
||||
} else {
|
||||
c.HTML(404, "index", data)
|
||||
}
|
||||
|
||||
c.HTML(404, "index")
|
||||
}
|
||||
|
||||
+7
-6
@@ -19,18 +19,19 @@ const (
|
||||
)
|
||||
|
||||
func LoginView(c *middleware.Context) {
|
||||
if err := setIndexViewData(c); err != nil {
|
||||
viewData, err := setIndexViewData(c)
|
||||
if err != nil {
|
||||
c.Handle(500, "Failed to get settings", err)
|
||||
return
|
||||
}
|
||||
|
||||
settings := c.Data["Settings"].(map[string]interface{})
|
||||
settings["googleAuthEnabled"] = setting.OAuthService.Google
|
||||
settings["githubAuthEnabled"] = setting.OAuthService.GitHub
|
||||
settings["disableUserSignUp"] = !setting.AllowUserSignUp
|
||||
viewData.Settings["googleAuthEnabled"] = setting.OAuthService.Google
|
||||
viewData.Settings["githubAuthEnabled"] = setting.OAuthService.GitHub
|
||||
viewData.Settings["disableUserSignUp"] = !setting.AllowUserSignUp
|
||||
viewData.Settings["loginHint"] = setting.LoginHint
|
||||
|
||||
if !tryLoginUsingRememberCookie(c) {
|
||||
c.HTML(200, VIEW_INDEX)
|
||||
c.HTML(200, VIEW_INDEX, viewData)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user