# Profiling APIs

SkyWalking offers two types of Profiling, in-process and out-process, each with its own API.

## In-process profiling APIs

[In-process profiling](../concepts-and-designs/profiling.md#in-process-profiling) commonly interacts with auto-instrument agents. It gathers stack traces of programs and sends the data to the OAP for further analysis.

```protobuf
syntax = "proto3";

package skywalking.v3;

option java_multiple_files = true;
option java_package = "org.apache.skywalking.apm.network.language.profile.v3";
option csharp_namespace = "SkyWalking.NetworkProtocol.V3";
option go_package = "skywalking.apache.org/repo/goapi/collect/language/profile/v3";

import "common/Command.proto";

service ProfileTask {

    // query all sniffer need to execute profile task commands
    rpc getProfileTaskCommands (ProfileTaskCommandQuery) returns (Commands) {
    }

    // collect dumped thread snapshot
    rpc collectSnapshot (stream ThreadSnapshot) returns (Commands) {
    }

    // report profiling task finished
    rpc reportTaskFinish (ProfileTaskFinishReport) returns (Commands) {
    }

}

message ProfileTaskCommandQuery {
    // current sniffer information
    string service = 1;
    string serviceInstance = 2;

    // last command timestamp
    int64 lastCommandTime = 3;
}

// dumped thread snapshot
message ThreadSnapshot {
    // profile task id
    string taskId = 1;
    // dumped segment id
    string traceSegmentId = 2;
    // dump timestamp
    int64 time = 3;
    // snapshot dump sequence, start with zero
    int32 sequence = 4;
    // snapshot stack
    ThreadStack stack = 5;
}

message ThreadStack {
    // stack code signature list
    repeated string codeSignatures = 1;
}

// profile task finished report
message ProfileTaskFinishReport {
    // current sniffer information
    string service = 1;
    string serviceInstance = 2;

    // profile task
    string taskId = 3;
}
```

## Out-process profiling

[Out-process profiling](../concepts-and-designs/profiling.md#out-of-process-profiling) interacts with eBPF agent, which receives tasks and captures data, then reports it to the OAP for further analysis.

### Process APIs

Similar to Service Instance, all processes must be reported to the OAP storage segment prior to analysis.

```protobuf
syntax = "proto3";

package skywalking.v3;

option java_multiple_files = true;
option java_package = "org.apache.skywalking.apm.network.ebpf.profiling.process.v3";
option go_package = "skywalking.apache.org/repo/goapi/collect/ebpf/profiling/process/v3";

import "common/Common.proto";
import "common/Command.proto";

// Define the detected processes and report them.
service EBPFProcessService {
    // Report discovered process in Rover
    rpc reportProcesses (EBPFProcessReportList) returns (EBPFReportProcessDownstream) {
    }

    // Keep the process alive in the backend.
    rpc keepAlive (EBPFProcessPingPkgList) returns (Commands) {
    }
}

message EBPFProcessReportList {
    repeated EBPFProcessProperties processes = 1;
    // An ID generated by eBPF agent, should be unique globally.
    string ebpfAgentID = 2;
}

message EBPFProcessProperties {
    // The Process metadata
    oneof metadata {
        EBPFHostProcessMetadata hostProcess = 1;
        EBPFKubernetesProcessMetadata k8sProcess = 2;
    }
}

message EBPFHostProcessMetadata {
    // [required] Entity metadata
    // Must ensure that entity information is unique at the time of reporting
    EBPFProcessEntityMetadata entity = 1;
    // [required] The Process id of the host
    int32 pid = 2;
    // [optional] properties of the process
    repeated KeyStringValuePair properties = 3;
}

// Process Entity metadata
message EBPFProcessEntityMetadata {
    // [required] Process belong layer name which define in the backend
    string layer = 1;
    // [required] Process belong service name
    string serviceName = 2;
    // [required] Process belong service instance name
    string instanceName = 3;
    // [required] Process name
    string processName = 4;
    // Process labels for aggregate from service
    repeated string labels = 5;
}

// Kubernetes process metadata
message EBPFKubernetesProcessMetadata {
    // [required] Entity metadata
    // Must ensure that entity information is unique at the time of reporting
    EBPFProcessEntityMetadata entity = 1;
    // [required] The Process id of the host
    int32 pid = 2;
    // [optional] properties of the process
    repeated KeyStringValuePair properties = 3;
}

message EBPFReportProcessDownstream {
    repeated EBPFProcessDownstream processes = 1;
}

message EBPFProcessDownstream {
    // Generated process id
    string processId = 1;
    // Locate the process by basic information
    oneof process {
        EBPFHostProcessDownstream hostProcess = 2;
        EBPFKubernetesProcessDownstream k8sProcess = 3;
    }
}

message EBPFHostProcessDownstream {
    int32 pid = 1;
    EBPFProcessEntityMetadata entityMetadata = 2;
}

// Kubernetes process downstream
message EBPFKubernetesProcessDownstream {
    int32 pid = 1;
    EBPFProcessEntityMetadata entityMetadata = 2;
}

message EBPFProcessPingPkgList {
    repeated EBPFProcessPingPkg processes = 1;
    // An ID generated by eBPF agent, should be unique globally.
    string ebpfAgentID = 2;
}

message EBPFProcessPingPkg {
    // Process entity
    EBPFProcessEntityMetadata entityMetadata = 1;
    // Minimize necessary properties
    repeated KeyStringValuePair properties = 2;
}
```

### Out-process profiling APIs

```protobuf
syntax = "proto3";

package skywalking.v3;

option java_multiple_files = true;
option java_package = "org.apache.skywalking.apm.network.ebpf.profiling.v3";
option go_package = "skywalking.apache.org/repo/goapi/collect/ebpf/profiling/v3";

import "common/Command.proto";

// Define the Rover Process profiling task and upload profiling data.
service EBPFProfilingService {
    // Query profiling (start or stop) tasks
    rpc queryTasks (EBPFProfilingTaskQuery) returns (Commands) {
    }

    // collect profiling data
    rpc collectProfilingData (stream EBPFProfilingData) returns (Commands) {
    }
}

message EBPFProfilingTaskQuery {
    // rover instance id
    string roverInstanceId = 1;

    // latest task update time
    int64 latestUpdateTime = 2;
}

message EBPFProfilingData {
    // task metadata
    EBPFProfilingTaskMetadata task = 1;
    // profiling data
    oneof profiling {
        EBPFOnCPUProfiling onCPU = 2;
        EBPFOffCPUProfiling offCPU = 3;
    }
}

message EBPFProfilingTaskMetadata {
    // profiling task id
    string taskId = 1;
    // profiling process id
    string processId = 2;
    // the start time of this profiling process
    int64 profilingStartTime = 3;
    // report time
    int64 currentTime = 4;
}

message EBPFProfilingStackMetadata {
    // stack type
    EBPFProfilingStackType stackType = 1;
    // stack id from kernel provide
    int32 stackId = 2;
    // stack symbols
    repeated string stackSymbols = 3;
}

enum EBPFProfilingStackType {
    PROCESS_KERNEL_SPACE = 0;
    PROCESS_USER_SPACE = 1;
}

message EBPFOnCPUProfiling {
    // stack data in one task(thread)
    repeated EBPFProfilingStackMetadata stacks = 1;
    // stack counts
    int32 dumpCount = 2;
}

message EBPFOffCPUProfiling {
    // stack data in one task(thread)
    repeated EBPFProfilingStackMetadata stacks = 1;
    // total count of the process is switched to off cpu by the scheduler.
    int32 switchCount = 2;
    // where time(nanoseconds) is spent waiting while blocked on I/O, locks, timers, paging/swapping, etc.
    int64 duration = 3;
}
```