1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
package fieldextractors
import (
"strings"
"gitlab.com/gitlab-org/gitaly/v14/proto/go/gitalypb"
)
type repositoryBasedRequest interface {
GetRepository() *gitalypb.Repository
}
type namespaceBasedRequest interface {
storageBasedRequest
GetName() string
}
type storageBasedRequest interface {
GetStorageName() string
}
func formatRepoRequest(repo *gitalypb.Repository) map[string]interface{} {
if repo == nil {
// Signals that the client did not send a repo through, which
// will be useful for logging
return map[string]interface{}{
"repo": nil,
}
}
return map[string]interface{}{
"repoStorage": repo.StorageName,
"repoPath": repo.RelativePath,
"topLevelGroup": getTopLevelGroupFromRepoPath(repo.RelativePath),
"glRepository": repo.GlRepository,
"glProjectPath": repo.GlProjectPath,
}
}
// getTopLevelGroupFromRepoPath gives the top-level group name, given
// a repoPath. For example:
// - "gitlab-org/gitlab-ce.git" returns "gitlab-org"
// - "gitlab-org/gitter/webapp.git" returns "gitlab-org"
// - "x.git" returns ""
func getTopLevelGroupFromRepoPath(repoPath string) string {
parts := strings.SplitN(repoPath, "/", 2)
if len(parts) != 2 {
return ""
}
return parts[0]
}
func formatStorageRequest(storageReq storageBasedRequest) map[string]interface{} {
return map[string]interface{}{
"StorageName": storageReq.GetStorageName(),
}
}
func formatNamespaceRequest(namespaceReq namespaceBasedRequest) map[string]interface{} {
return map[string]interface{}{
"StorageName": namespaceReq.GetStorageName(),
"Name": namespaceReq.GetName(),
}
}
func formatRenameNamespaceRequest(renameReq *gitalypb.RenameNamespaceRequest) map[string]interface{} {
return map[string]interface{}{
"StorageName": renameReq.GetStorageName(),
"From": renameReq.GetFrom(),
"To": renameReq.GetTo(),
}
}
// FieldExtractor will extract the relevant fields from an incoming grpc request
func FieldExtractor(fullMethod string, req interface{}) map[string]interface{} {
if req == nil {
return nil
}
var result map[string]interface{}
switch req := req.(type) {
case *gitalypb.RenameNamespaceRequest:
result = formatRenameNamespaceRequest(req)
case repositoryBasedRequest:
result = formatRepoRequest(req.GetRepository())
case namespaceBasedRequest:
result = formatNamespaceRequest(req)
case storageBasedRequest:
result = formatStorageRequest(req)
}
if result == nil {
result = make(map[string]interface{})
}
switch {
case strings.HasPrefix(fullMethod, "/gitaly.ObjectPoolService/"):
addObjectPool(req, result)
}
result["fullMethod"] = fullMethod
return result
}
type objectPoolRequest interface {
GetObjectPool() *gitalypb.ObjectPool
}
func addObjectPool(req interface{}, tags map[string]interface{}) {
oReq, ok := req.(objectPoolRequest)
if !ok {
return
}
pool := oReq.GetObjectPool()
if pool == nil {
return
}
repo := pool.GetRepository()
if repo == nil {
return
}
for k, v := range map[string]string{
"pool.storage": repo.StorageName,
"pool.relativePath": repo.RelativePath,
"pool.sourceProjectPath": repo.GlProjectPath,
} {
tags[k] = v
}
}
|