...

Source file src/github.com/go-kivik/kivik/v4/couchdb/dbstats.go

Documentation: github.com/go-kivik/kivik/v4/couchdb

     1  // Licensed under the Apache License, Version 2.0 (the "License"); you may not
     2  // use this file except in compliance with the License. You may obtain a copy of
     3  // the License at
     4  //
     5  //  http://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     9  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    10  // License for the specific language governing permissions and limitations under
    11  // the License.
    12  
    13  package couchdb
    14  
    15  import (
    16  	"bytes"
    17  	"context"
    18  	"encoding/json"
    19  	"net/http"
    20  
    21  	"github.com/go-kivik/kivik/v4/couchdb/chttp"
    22  	"github.com/go-kivik/kivik/v4/driver"
    23  )
    24  
    25  type dbStats struct {
    26  	driver.DBStats
    27  	Sizes struct {
    28  		File     int64 `json:"file"`
    29  		External int64 `json:"external"`
    30  		Active   int64 `json:"active"`
    31  	} `json:"sizes"`
    32  	UpdateSeq json.RawMessage `json:"update_seq"` // nolint: govet
    33  	rawBody   json.RawMessage
    34  }
    35  
    36  func (s *dbStats) UnmarshalJSON(p []byte) error {
    37  	type dbStatsClone dbStats
    38  	c := dbStatsClone(*s)
    39  	if err := json.Unmarshal(p, &c); err != nil {
    40  		return err
    41  	}
    42  	*s = dbStats(c)
    43  	s.rawBody = p
    44  	return nil
    45  }
    46  
    47  func (s *dbStats) driverStats() *driver.DBStats {
    48  	stats := &s.DBStats
    49  	if s.Sizes.File > 0 {
    50  		stats.DiskSize = s.Sizes.File
    51  	}
    52  	if s.Sizes.External > 0 {
    53  		stats.ExternalSize = s.Sizes.External
    54  	}
    55  	if s.Sizes.Active > 0 {
    56  		stats.ActiveSize = s.Sizes.Active
    57  	}
    58  	stats.UpdateSeq = string(bytes.Trim(s.UpdateSeq, `"`))
    59  	stats.RawResponse = s.rawBody
    60  	return stats
    61  }
    62  
    63  func (d *db) Stats(ctx context.Context) (*driver.DBStats, error) {
    64  	result := dbStats{}
    65  	if err := d.Client.DoJSON(ctx, http.MethodGet, d.dbName, nil, &result); err != nil {
    66  		return nil, err
    67  	}
    68  	return result.driverStats(), nil
    69  }
    70  
    71  type dbsInfoRequest struct {
    72  	Keys []string `json:"keys"`
    73  }
    74  
    75  type dbsInfoResponse struct {
    76  	Key    string  `json:"key"`
    77  	DBInfo dbStats `json:"info"`
    78  	Error  string  `json:"error"`
    79  }
    80  
    81  func (c *client) DBsStats(_ context.Context, dbnames []string) ([]*driver.DBStats, error) {
    82  	opts := &chttp.Options{
    83  		GetBody: chttp.BodyEncoder(dbsInfoRequest{Keys: dbnames}),
    84  		Header: http.Header{
    85  			chttp.HeaderIdempotencyKey: []string{},
    86  		},
    87  	}
    88  	result := []dbsInfoResponse{}
    89  	err := c.DoJSON(context.Background(), http.MethodPost, "/_dbs_info", opts, &result)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  	stats := make([]*driver.DBStats, len(result))
    94  	for i := range result {
    95  		if result[i].Error == "" {
    96  			stats[i] = result[i].DBInfo.driverStats()
    97  		}
    98  	}
    99  	return stats, nil
   100  }
   101  
   102  func (c *client) AllDBsStats(ctx context.Context, options driver.Options) ([]*driver.DBStats, error) {
   103  	opts := map[string]interface{}{}
   104  	options.Apply(opts)
   105  	chttpOpts := &chttp.Options{
   106  		Header: http.Header{
   107  			chttp.HeaderIdempotencyKey: []string{},
   108  		},
   109  	}
   110  	var err error
   111  	chttpOpts.Query, err = optionsToParams(opts)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	result := []dbsInfoResponse{}
   116  	if err := c.DoJSON(ctx, http.MethodGet, "/_dbs_info", chttpOpts, &result); err != nil {
   117  		return nil, err
   118  	}
   119  	stats := make([]*driver.DBStats, len(result))
   120  	for i := range result {
   121  		stats[i] = result[i].DBInfo.driverStats()
   122  	}
   123  	return stats, nil
   124  }
   125  
   126  type partitionStats struct {
   127  	DBName      string `json:"db_name"`
   128  	DocCount    int64  `json:"doc_count"`
   129  	DocDelCount int64  `json:"doc_del_count"`
   130  	Partition   string `json:"partition"`
   131  	Sizes       struct {
   132  		Active   int64 `json:"active"`
   133  		External int64 `json:"external"`
   134  	}
   135  	rawBody json.RawMessage
   136  }
   137  
   138  func (s *partitionStats) UnmarshalJSON(p []byte) error {
   139  	c := struct {
   140  		partitionStats
   141  		UnmarshalJSON struct{}
   142  	}{}
   143  	if err := json.Unmarshal(p, &c); err != nil {
   144  		return err
   145  	}
   146  	*s = c.partitionStats
   147  	s.rawBody = p
   148  	return nil
   149  }
   150  
   151  func (d *db) PartitionStats(ctx context.Context, name string) (*driver.PartitionStats, error) {
   152  	result := partitionStats{}
   153  	if err := d.Client.DoJSON(ctx, http.MethodGet, d.path("_partition/"+name), nil, &result); err != nil {
   154  		return nil, err
   155  	}
   156  	return &driver.PartitionStats{
   157  		DBName:          result.DBName,
   158  		DocCount:        result.DocCount,
   159  		DeletedDocCount: result.DocDelCount,
   160  		Partition:       result.Partition,
   161  		ActiveSize:      result.Sizes.Active,
   162  		ExternalSize:    result.Sizes.External,
   163  		RawResponse:     result.rawBody,
   164  	}, nil
   165  }
   166  

View as plain text