feat: move metrics actions and service to tags

This commit is contained in:
Ben McClelland
2024-05-29 15:36:21 -07:00
parent e730d3d9a6
commit 97b5424e07
5 changed files with 271 additions and 34 deletions

View File

@@ -14,6 +14,15 @@
package metrics
type Action struct {
Name string
Service string
}
var (
ActionMap map[string]Action
)
var (
ActionUndetected = "ActionUnDetected"
ActionAbortMultipartUpload = "s3_AbortMultipartUpload"
@@ -61,3 +70,189 @@ var (
ActionUploadPart = "s3_UploadPart"
ActionUploadPartCopy = "s3_UploadPartCopy"
)
func init() {
ActionMap = make(map[string]Action)
ActionMap[ActionUndetected] = Action{
Name: "ActionUnDetected",
Service: "unknown",
}
ActionMap[ActionAbortMultipartUpload] = Action{
Name: "AbortMultipartUpload",
Service: "s3",
}
ActionMap[ActionCompleteMultipartUpload] = Action{
Name: "CompleteMultipartUpload",
Service: "s3",
}
ActionMap[ActionCopyObject] = Action{
Name: "CopyObject",
Service: "s3",
}
ActionMap[ActionCreateBucket] = Action{
Name: "CreateBucket",
Service: "s3",
}
ActionMap[ActionCreateMultipartUpload] = Action{
Name: "CreateMultipartUpload",
Service: "s3",
}
ActionMap[ActionDeleteBucket] = Action{
Name: "DeleteBucket",
Service: "s3",
}
ActionMap[ActionDeleteBucketPolicy] = Action{
Name: "DeleteBucketPolicy",
Service: "s3",
}
ActionMap[ActionDeleteBucketTagging] = Action{
Name: "DeleteBucketTagging",
Service: "s3",
}
ActionMap[ActionDeleteObject] = Action{
Name: "DeleteObject",
Service: "s3",
}
ActionMap[ActionDeleteObjectTagging] = Action{
Name: "DeleteObjectTagging",
Service: "s3",
}
ActionMap[ActionDeleteObjects] = Action{
Name: "DeleteObjects",
Service: "s3",
}
ActionMap[ActionGetBucketAcl] = Action{
Name: "GetBucketAcl",
Service: "s3",
}
ActionMap[ActionGetBucketPolicy] = Action{
Name: "GetBucketPolicy",
Service: "s3",
}
ActionMap[ActionGetBucketTagging] = Action{
Name: "GetBucketTagging",
Service: "s3",
}
ActionMap[ActionGetBucketVersioning] = Action{
Name: "GetBucketVersioning",
Service: "s3",
}
ActionMap[ActionGetObject] = Action{
Name: "GetObject",
Service: "s3",
}
ActionMap[ActionGetObjectAcl] = Action{
Name: "GetObjectAcl",
Service: "s3",
}
ActionMap[ActionGetObjectAttributes] = Action{
Name: "GetObjectAttributes",
Service: "s3",
}
ActionMap[ActionGetObjectLegalHold] = Action{
Name: "GetObjectLegalHold",
Service: "s3",
}
ActionMap[ActionGetObjectLockConfiguration] = Action{
Name: "GetObjectLockConfiguration",
Service: "s3",
}
ActionMap[ActionGetObjectRetention] = Action{
Name: "GetObjectRetention",
Service: "s3",
}
ActionMap[ActionGetObjectTagging] = Action{
Name: "GetObjectTagging",
Service: "s3",
}
ActionMap[ActionHeadBucket] = Action{
Name: "HeadBucket",
Service: "s3",
}
ActionMap[ActionHeadObject] = Action{
Name: "HeadObject",
Service: "s3",
}
ActionMap[ActionListAllMyBuckets] = Action{
Name: "ListAllMyBuckets",
Service: "s3",
}
ActionMap[ActionListMultipartUploads] = Action{
Name: "ListMultipartUploads",
Service: "s3",
}
ActionMap[ActionListObjectVersions] = Action{
Name: "ListObjectVersions",
Service: "s3",
}
ActionMap[ActionListObjects] = Action{
Name: "ListObjects",
Service: "s3",
}
ActionMap[ActionListObjectsV2] = Action{
Name: "ListObjectsV2",
Service: "s3",
}
ActionMap[ActionListParts] = Action{
Name: "ListParts",
Service: "s3",
}
ActionMap[ActionPutBucketAcl] = Action{
Name: "PutBucketAcl",
Service: "s3",
}
ActionMap[ActionPutBucketPolicy] = Action{
Name: "PutBucketPolicy",
Service: "s3",
}
ActionMap[ActionPutBucketTagging] = Action{
Name: "PutBucketTagging",
Service: "s3",
}
ActionMap[ActionPutBucketVersioning] = Action{
Name: "PutBucketVersioning",
Service: "s3",
}
ActionMap[ActionPutObject] = Action{
Name: "PutObject",
Service: "s3",
}
ActionMap[ActionPutObjectAcl] = Action{
Name: "PutObjectAcl",
Service: "s3",
}
ActionMap[ActionPutObjectLegalHold] = Action{
Name: "PutObjectLegalHold",
Service: "s3",
}
ActionMap[ActionPutObjectLockConfiguration] = Action{
Name: "PutObjectLockConfiguration",
Service: "s3",
}
ActionMap[ActionPutObjectRetention] = Action{
Name: "PutObjectRetention",
Service: "s3",
}
ActionMap[ActionPutObjectTagging] = Action{
Name: "PutObjectTagging",
Service: "s3",
}
ActionMap[ActionRestoreObject] = Action{
Name: "RestoreObject",
Service: "s3",
}
ActionMap[ActionSelectObjectContent] = Action{
Name: "SelectObjectContent",
Service: "s3",
}
ActionMap[ActionUploadPart] = Action{
Name: "UploadPart",
Service: "s3",
}
ActionMap[ActionUploadPartCopy] = Action{
Name: "UploadPartCopy",
Service: "s3",
}
}

View File

@@ -1,3 +1,17 @@
// Copyright 2024 Versity Software
// This file is licensed under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package metrics
import (
@@ -42,10 +56,10 @@ func (t Tag) ddString() string {
}
// Add adds value to key
func (s *vgwDogStatsd) Add(module, key string, value int64, tags ...Tag) {
func (s *vgwDogStatsd) Add(key string, value int64, tags ...Tag) {
stags := make([]string, len(tags))
for i, t := range tags {
stags[i] = t.ddString()
}
s.c.Count(fmt.Sprintf("%v.%v", module, key), value, stags, rateSampleAlways)
s.c.Count(key, value, stags, rateSampleAlways)
}

View File

@@ -16,10 +16,15 @@ package metrics
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"strings"
"sync"
"github.com/gofiber/fiber/v2"
"github.com/versity/versitygw/s3err"
)
var (
@@ -107,50 +112,76 @@ func NewManager(ctx context.Context, conf Config) (*Manager, error) {
return mgr, nil
}
func (m *Manager) Send(err error, action string, count int64) {
func (m *Manager) Send(ctx *fiber.Ctx, err error, action string, count int64, status int) {
// In case of Authentication failures, url parsing ...
if action == "" {
action = ActionUndetected
}
a := ActionMap[action]
reqTags := []Tag{
{Key: "method", Value: ctx.Method()},
{Key: "api", Value: a.Service},
{Key: "action", Value: a.Name},
}
reqStatus := status
if err != nil {
m.increment(action, "failed_count")
var apierr s3err.APIError
if errors.As(err, &apierr) {
reqStatus = apierr.HTTPStatusCode
} else {
reqStatus = http.StatusInternalServerError
}
}
if reqStatus == 0 {
reqStatus = http.StatusOK
}
reqTags = append(reqTags, Tag{
Key: "status",
Value: fmt.Sprintf("%v", reqStatus),
})
if err != nil {
m.increment("failed_count", reqTags...)
} else {
m.increment(action, "success_count")
m.increment("success_count", reqTags...)
}
switch action {
case ActionPutObject:
m.add(action, "bytes_written", count)
m.increment(action, "object_created_count")
m.add("bytes_written", count, reqTags...)
m.increment("object_created_count", reqTags...)
case ActionCompleteMultipartUpload:
m.increment(action, "object_created_count")
m.increment("object_created_count", reqTags...)
case ActionUploadPart:
m.add(action, "bytes_written", count)
m.add("bytes_written", count, reqTags...)
case ActionGetObject:
m.add(action, "bytes_read", count)
m.add("bytes_read", count, reqTags...)
case ActionDeleteObject:
m.increment(action, "object_removed_count")
m.increment("object_removed_count", reqTags...)
case ActionDeleteObjects:
m.add(action, "object_removed_count", count)
m.add("object_removed_count", count, reqTags...)
}
}
// increment increments the key by one
func (m *Manager) increment(module, key string, tags ...Tag) {
m.add(module, key, 1, tags...)
func (m *Manager) increment(key string, tags ...Tag) {
m.add(key, 1, tags...)
}
// add adds value to key
func (m *Manager) add(module, key string, value int64, tags ...Tag) {
func (m *Manager) add(key string, value int64, tags ...Tag) {
if m.ctx.Err() != nil {
return
}
d := datapoint{
module: module,
key: key,
value: value,
tags: tags,
key: key,
value: value,
tags: tags,
}
select {
@@ -174,22 +205,21 @@ func (m *Manager) Close() {
// publisher is the interface for interacting with the metrics plugins
type publisher interface {
Add(module, key string, value int64, tags ...Tag)
Add(key string, value int64, tags ...Tag)
Close()
}
func (m *Manager) addForwarder(addChan <-chan datapoint) {
for data := range addChan {
for _, s := range m.publishers {
s.Add(data.module, data.key, data.value, data.tags...)
s.Add(data.key, data.value, data.tags...)
}
}
m.wg.Done()
}
type datapoint struct {
module string
key string
value int64
tags []Tag
key string
value int64
tags []Tag
}

View File

@@ -15,8 +15,6 @@
package metrics
import (
"fmt"
"github.com/smira/go-statsd"
)
@@ -44,10 +42,10 @@ func (s *vgwStatsd) Close() {
}
// Add adds value to key
func (s *vgwStatsd) Add(module, key string, value int64, tags ...Tag) {
func (s *vgwStatsd) Add(key string, value int64, tags ...Tag) {
stags := make([]statsd.Tag, len(tags))
for i, t := range tags {
stags[i] = statsd.StringTag(t.Key, t.Value)
}
s.c.Incr(fmt.Sprintf("%v.%v", module, key), value, stags...)
s.c.Incr(key, value, stags...)
}

View File

@@ -2753,7 +2753,7 @@ func (c S3ApiController) CreateActions(ctx *fiber.Ctx) error {
&MetaOpts{
Logger: c.logger,
MetricsMng: c.mm,
Action: "CreateMultipartUpload",
Action: metrics.ActionCreateMultipartUpload,
BucketOwner: parsedAcl.Owner,
})
}
@@ -2805,9 +2805,9 @@ func SendResponse(ctx *fiber.Ctx, err error, l *MetaOpts) error {
}
if l.MetricsMng != nil {
if l.ObjectCount > 0 {
l.MetricsMng.Send(err, l.Action, l.ObjectCount)
l.MetricsMng.Send(ctx, err, l.Action, l.ObjectCount, l.Status)
} else {
l.MetricsMng.Send(err, l.Action, l.ContentLength)
l.MetricsMng.Send(ctx, err, l.Action, l.ContentLength, l.Status)
}
}
if err != nil {
@@ -2854,9 +2854,9 @@ const (
func SendXMLResponse(ctx *fiber.Ctx, resp any, err error, l *MetaOpts) error {
if l.MetricsMng != nil {
if l.ObjectCount > 0 {
l.MetricsMng.Send(err, l.Action, l.ObjectCount)
l.MetricsMng.Send(ctx, err, l.Action, l.ObjectCount, l.Status)
} else {
l.MetricsMng.Send(err, l.Action, l.ContentLength)
l.MetricsMng.Send(ctx, err, l.Action, l.ContentLength, l.Status)
}
}
if err != nil {