You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

155 lines
4.8 KiB

  1. // Copyright 2016 Google LLC
  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. package logadmin
  15. import (
  16. "context"
  17. "fmt"
  18. vkit "cloud.google.com/go/logging/apiv2"
  19. "google.golang.org/api/iterator"
  20. logpb "google.golang.org/genproto/googleapis/logging/v2"
  21. )
  22. // Metric describes a logs-based metric. The value of the metric is the
  23. // number of log entries that match a logs filter.
  24. //
  25. // Metrics are a feature of Stackdriver Monitoring.
  26. // See https://cloud.google.com/monitoring/api/v3/metrics for more about them.
  27. type Metric struct {
  28. // ID is a client-assigned metric identifier. Example:
  29. // "severe_errors". Metric identifiers are limited to 1000
  30. // characters and can include only the following characters: A-Z,
  31. // a-z, 0-9, and the special characters _-.,+!*',()%/\. The
  32. // forward-slash character (/) denotes a hierarchy of name pieces,
  33. // and it cannot be the first character of the name.
  34. ID string
  35. // Description describes this metric. It is used in documentation.
  36. Description string
  37. // Filter is an advanced logs filter (see
  38. // https://cloud.google.com/logging/docs/view/advanced_filters).
  39. // Example: "logName:syslog AND severity>=ERROR".
  40. Filter string
  41. }
  42. // CreateMetric creates a logs-based metric.
  43. func (c *Client) CreateMetric(ctx context.Context, m *Metric) error {
  44. _, err := c.mClient.CreateLogMetric(ctx, &logpb.CreateLogMetricRequest{
  45. Parent: c.parent,
  46. Metric: toLogMetric(m),
  47. })
  48. return err
  49. }
  50. // DeleteMetric deletes a log-based metric.
  51. // The provided metric ID is the metric identifier. For example, "severe_errors".
  52. func (c *Client) DeleteMetric(ctx context.Context, metricID string) error {
  53. return c.mClient.DeleteLogMetric(ctx, &logpb.DeleteLogMetricRequest{
  54. MetricName: c.metricPath(metricID),
  55. })
  56. }
  57. // Metric gets a logs-based metric.
  58. // The provided metric ID is the metric identifier. For example, "severe_errors".
  59. // Requires ReadScope or AdminScope.
  60. func (c *Client) Metric(ctx context.Context, metricID string) (*Metric, error) {
  61. lm, err := c.mClient.GetLogMetric(ctx, &logpb.GetLogMetricRequest{
  62. MetricName: c.metricPath(metricID),
  63. })
  64. if err != nil {
  65. return nil, err
  66. }
  67. return fromLogMetric(lm), nil
  68. }
  69. // UpdateMetric creates a logs-based metric if it does not exist, or updates an
  70. // existing one.
  71. func (c *Client) UpdateMetric(ctx context.Context, m *Metric) error {
  72. _, err := c.mClient.UpdateLogMetric(ctx, &logpb.UpdateLogMetricRequest{
  73. MetricName: c.metricPath(m.ID),
  74. Metric: toLogMetric(m),
  75. })
  76. return err
  77. }
  78. func (c *Client) metricPath(metricID string) string {
  79. return fmt.Sprintf("%s/metrics/%s", c.parent, metricID)
  80. }
  81. // Metrics returns a MetricIterator for iterating over all Metrics in the Client's project.
  82. // Requires ReadScope or AdminScope.
  83. func (c *Client) Metrics(ctx context.Context) *MetricIterator {
  84. it := &MetricIterator{
  85. it: c.mClient.ListLogMetrics(ctx, &logpb.ListLogMetricsRequest{Parent: c.parent}),
  86. }
  87. it.pageInfo, it.nextFunc = iterator.NewPageInfo(
  88. it.fetch,
  89. func() int { return len(it.items) },
  90. func() interface{} { b := it.items; it.items = nil; return b })
  91. return it
  92. }
  93. // A MetricIterator iterates over Metrics.
  94. type MetricIterator struct {
  95. it *vkit.LogMetricIterator
  96. pageInfo *iterator.PageInfo
  97. nextFunc func() error
  98. items []*Metric
  99. }
  100. // PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
  101. func (it *MetricIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
  102. // Next returns the next result. Its second return value is Done if there are
  103. // no more results. Once Next returns Done, all subsequent calls will return
  104. // Done.
  105. func (it *MetricIterator) Next() (*Metric, error) {
  106. if err := it.nextFunc(); err != nil {
  107. return nil, err
  108. }
  109. item := it.items[0]
  110. it.items = it.items[1:]
  111. return item, nil
  112. }
  113. func (it *MetricIterator) fetch(pageSize int, pageToken string) (string, error) {
  114. return iterFetch(pageSize, pageToken, it.it.PageInfo(), func() error {
  115. item, err := it.it.Next()
  116. if err != nil {
  117. return err
  118. }
  119. it.items = append(it.items, fromLogMetric(item))
  120. return nil
  121. })
  122. }
  123. func toLogMetric(m *Metric) *logpb.LogMetric {
  124. return &logpb.LogMetric{
  125. Name: m.ID,
  126. Description: m.Description,
  127. Filter: m.Filter,
  128. }
  129. }
  130. func fromLogMetric(lm *logpb.LogMetric) *Metric {
  131. return &Metric{
  132. ID: lm.Name,
  133. Description: lm.Description,
  134. Filter: lm.Filter,
  135. }
  136. }