| // Licensed to Apache Software Foundation (ASF) under one or more contributor |
| // license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright |
| // ownership. Apache Software Foundation (ASF) licenses this file to you 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 base |
| |
| import ( |
| "encoding/json" |
| "fmt" |
| "strconv" |
| "strings" |
| "time" |
| |
| "github.com/apache/skywalking-rover/pkg/process/api" |
| |
| v3 "skywalking.apache.org/repo/goapi/collect/common/v3" |
| ) |
| |
| type ProfilingTask struct { |
| // TaskID of profiling task |
| TaskID string |
| // ProcessIDList of need to monitoring process |
| ProcessIDList []string |
| // UpdateTime of profiling task |
| UpdateTime int64 |
| // StartTime of profiling task, when need to start to profiling |
| StartTime int64 |
| // TriggerType of task |
| TriggerType TriggerType |
| // TargetType of task |
| TargetType TargetType |
| // MaxRunningDuration of task |
| MaxRunningDuration time.Duration |
| ExtensionConfig *ExtensionConfig |
| } |
| |
| func ProfilingTaskFromCommand(command *v3.Command) (*ProfilingTask, error) { |
| if command.GetCommand() != "EBPFProfilingTaskQuery" { |
| return nil, fmt.Errorf("not support command: %s", command.GetCommand()) |
| } |
| |
| var err error |
| taskID, err := getCommandStringValue(err, command, "TaskId") |
| processIDList, err := getCommandStringValue(err, command, "ProcessId") |
| taskUpdateTime, err := getCommandIntValue(err, command, "TaskUpdateTime") |
| triggerTypeStr, err := getCommandStringValue(err, command, "TriggerType") |
| triggerType, err := ParseTriggerType(err, triggerTypeStr) |
| targetTypeStr, err := getCommandStringValue(err, command, "TargetType") |
| targetType, err := ParseTargetType(err, targetTypeStr) |
| taskStartTime, err := getCommandIntValue(err, command, "TaskStartTime") |
| extensionConfig, err := getCommandExtensionConfig(err, command, "ExtensionConfigJSON") |
| if err != nil { |
| return nil, err |
| } |
| |
| processes := strings.Split(processIDList, ",") |
| |
| task := &ProfilingTask{ |
| TaskID: taskID, |
| ProcessIDList: processes, |
| UpdateTime: taskUpdateTime, |
| StartTime: taskStartTime, |
| TargetType: targetType, |
| TriggerType: triggerType, |
| ExtensionConfig: extensionConfig, |
| } |
| |
| if err := task.TriggerType.InitTask(task, command); err != nil { |
| return nil, err |
| } |
| if err := task.TargetType.InitTask(task, command); err != nil { |
| return nil, err |
| } |
| |
| return task, nil |
| } |
| |
| func ProfilingTaskFromContinuous(processes []api.ProcessInterface, taskSetter func(task *ProfilingTask)) *ProfilingTask { |
| processesIDList := make([]string, 0) |
| for _, p := range processes { |
| processesIDList = append(processesIDList, p.ID()) |
| } |
| task := &ProfilingTask{ |
| ProcessIDList: processesIDList, |
| UpdateTime: 0, |
| StartTime: 0, |
| TriggerType: TriggerTypeFixedTime, |
| } |
| taskSetter(task) |
| |
| return task |
| } |
| |
| type ExtensionConfig struct { |
| NetworkSamplings []*NetworkSamplingRule `json:"NetworkSamplings"` |
| } |
| |
| type NetworkSamplingRule struct { |
| URIRegex *string `json:"URIRegex"` |
| MinDuration *int32 `json:"MinDuration"` |
| When4XX bool `json:"When4xx"` |
| When5XX bool `json:"When5xx"` |
| Settings *NetworkDataCollectingSettings `json:"Settings"` |
| } |
| |
| type NetworkDataCollectingSettings struct { |
| RequireCompleteRequest bool `json:"RequireCompleteRequest"` |
| MaxRequestSize int32 `json:"MaxRequestSize"` |
| RequireCompleteResponse bool `json:"RequireCompleteResponse"` |
| MaxResponseSize int32 `json:"MaxResponseSize"` |
| } |
| |
| func getCommandStringValue(err error, command *v3.Command, key string) (string, error) { |
| if err != nil { |
| return "", err |
| } |
| for _, arg := range command.GetArgs() { |
| if arg.GetKey() == key { |
| return arg.GetValue(), nil |
| } |
| } |
| return "", fmt.Errorf("could not found key: %v", key) |
| } |
| |
| func getCommandIntValue(err error, command *v3.Command, key string) (int64, error) { |
| val, err := getCommandStringValue(err, command, key) |
| if err != nil { |
| return 0, err |
| } |
| return strconv.ParseInt(val, 10, 64) |
| } |
| |
| func getCommandExtensionConfig(err error, command *v3.Command, key string) (*ExtensionConfig, error) { |
| val, err := getCommandStringValue(err, command, key) |
| if err != nil { |
| return nil, err |
| } |
| config := &ExtensionConfig{} |
| if e := json.Unmarshal([]byte(val), config); e != nil { |
| return nil, e |
| } |
| return config, nil |
| } |