mirror of https://github.com/linkerd/linkerd2.git
120 lines
3.1 KiB
Go
120 lines
3.1 KiB
Go
package cmd
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"time"
|
|
|
|
pkgcmd "github.com/linkerd/linkerd2/pkg/cmd"
|
|
"github.com/linkerd/linkerd2/pkg/k8s"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
type metricsOptions struct {
|
|
namespace string
|
|
pod string
|
|
obfuscate bool
|
|
}
|
|
|
|
func newMetricsOptions() *metricsOptions {
|
|
return &metricsOptions{
|
|
pod: "",
|
|
obfuscate: false,
|
|
}
|
|
}
|
|
|
|
func newCmdMetrics() *cobra.Command {
|
|
options := newMetricsOptions()
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "proxy-metrics [flags] (RESOURCE)",
|
|
Short: "Fetch metrics directly from Linkerd proxies",
|
|
Long: `Fetch metrics directly from Linkerd proxies.
|
|
|
|
This command initiates a port-forward to a given pod or set of pods, and
|
|
queries the /metrics endpoint on the Linkerd proxies.
|
|
|
|
The RESOURCE argument specifies the target resource to query metrics for:
|
|
(TYPE/NAME)
|
|
|
|
Examples:
|
|
* cronjob/my-cronjob
|
|
* deploy/my-deploy
|
|
* ds/my-daemonset
|
|
* job/my-job
|
|
* po/mypod1
|
|
* rc/my-replication-controller
|
|
* sts/my-statefulset
|
|
|
|
Valid resource types include:
|
|
* cronjobs
|
|
* daemonsets
|
|
* deployments
|
|
* jobs
|
|
* pods
|
|
* replicasets
|
|
* replicationcontrollers
|
|
* statefulsets`,
|
|
Example: ` # Get metrics from pod-foo-bar in the default namespace.
|
|
linkerd diagnostics proxy-metrics po/pod-foo-bar
|
|
|
|
# Get metrics from the web deployment in the emojivoto namespace.
|
|
linkerd diagnostics proxy-metrics -n emojivoto deploy/web
|
|
|
|
# Get metrics from the linkerd-destination pod in the linkerd namespace.
|
|
linkerd diagnostics proxy-metrics -n linkerd $(
|
|
kubectl --namespace linkerd get pod \
|
|
--selector linkerd.io/control-plane-component=destination \
|
|
--output name
|
|
)`,
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
if options.namespace == "" {
|
|
options.namespace = pkgcmd.GetDefaultNamespace(kubeconfigPath, kubeContext)
|
|
}
|
|
k8sAPI, err := k8s.NewAPI(kubeconfigPath, kubeContext, impersonate, impersonateGroup, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
pods, err := k8s.GetPodsFor(cmd.Context(), k8sAPI, options.namespace, args[0])
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
results := getMetrics(k8sAPI, pods, k8s.ProxyAdminPortName, 30*time.Second, verbose)
|
|
|
|
var buf bytes.Buffer
|
|
for i, result := range results {
|
|
content := fmt.Sprintf("#\n# POD %s (%d of %d)\n#\n", result.pod, i+1, len(results))
|
|
switch {
|
|
case result.err != nil:
|
|
content += fmt.Sprintf("# ERROR: %s\n", result.err)
|
|
case options.obfuscate:
|
|
obfuscatedMetrics, err := obfuscateMetrics(result.metrics)
|
|
if err != nil {
|
|
content += fmt.Sprintf("# ERROR %s\n", err)
|
|
} else {
|
|
content += string(obfuscatedMetrics)
|
|
}
|
|
default:
|
|
content += string(result.metrics)
|
|
}
|
|
|
|
buf.WriteString(content)
|
|
}
|
|
fmt.Printf("%s", buf.String())
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
cmd.PersistentFlags().StringVarP(&options.namespace, "namespace", "n", options.namespace, "Namespace of resource")
|
|
cmd.PersistentFlags().BoolVar(&options.obfuscate, "obfuscate", options.obfuscate, "Obfuscate sensitive information")
|
|
|
|
pkgcmd.ConfigureNamespaceFlagCompletion(cmd, []string{"namespace"},
|
|
kubeconfigPath, impersonate, impersonateGroup, kubeContext)
|
|
|
|
return cmd
|
|
}
|