/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * 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.
 */

syntax = "proto2";
package perfetto.protos;

import "protos/perfetto/common/sys_stats_counters.proto";

// Various Linux system stat counters from /proc.
// The fields in this message can be reported at different rates and with
// different granularity. See sys_stats_config.proto.
message SysStats {
  // Counters from /proc/meminfo. Values are in KB.
  message MeminfoValue {
    optional MeminfoCounters key = 1;
    optional uint64 value = 2;
  };
  repeated MeminfoValue meminfo = 1;

  // Counter from /proc/vmstat. Units are often pages, not KB.
  message VmstatValue {
    optional VmstatCounters key = 1;
    optional uint64 value = 2;
  };
  repeated VmstatValue vmstat = 2;

  // Times in each mode, since boot. Unit: nanoseconds.
  message CpuTimes {
    optional uint32 cpu_id = 1;

    // Time spent in user mode.
    optional uint64 user_ns = 2;

    // Time spent in user mode (low prio).
    optional uint64 user_nice_ns = 3;

    // Time spent in system mode.
    optional uint64 system_mode_ns = 4;

    // Time spent in the idle task.
    optional uint64 idle_ns = 5;

    // Time spent waiting for I/O.
    optional uint64 io_wait_ns = 6;

    // Time spent servicing interrupts.
    optional uint64 irq_ns = 7;

    // Time spent servicing softirqs.
    optional uint64 softirq_ns = 8;

    // Time spent executing something else on host than this guest.
    optional uint64 steal_ns = 9;
  }
  // One entry per cpu.
  repeated CpuTimes cpu_stat = 3;

  // Num processes forked since boot.
  // Populated only if FORK_COUNT in config.stat_counters.
  optional uint64 num_forks = 4;

  message InterruptCount {
    optional int32 irq = 1;
    optional uint64 count = 2;
  }

  // Number of interrupts, broken by IRQ number.
  // Populated only if IRQ_COUNTS in config.stat_counters.

  // Total num of irqs serviced since boot.
  optional uint64 num_irq_total = 5;
  repeated InterruptCount num_irq = 6;

  // Number of softirqs, broken by softirq number.
  // Populated only if SOFTIRQ_COUNTS in config.stat_counters.

  // Total num of softirqs since boot.
  optional uint64 num_softirq_total = 7;

  // Per-softirq count.
  repeated InterruptCount num_softirq = 8;

  // The time at which we finish collecting this set of samples;
  // the top-level packet timestamp is the time at which
  // we begin collection.
  optional uint64 collection_end_timestamp = 9;

  // Frequencies for /sys/class/devfreq/ entries in kHz.
  message DevfreqValue {
    optional string key = 1;
    optional uint64 value = 2;
  };

  // One entry per device.
  repeated DevfreqValue devfreq = 10;

  // Cpu current frequency from
  // /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_cur_freq in kHz.
  // One entry per cpu. Report 0 for offline cpu
  repeated uint32 cpufreq_khz = 11;

  message BuddyInfo {
    optional string node = 1;
    optional string zone = 2;
    repeated uint32 order_pages = 3;
  }
  // One entry per each node's zones.
  repeated BuddyInfo buddy_info = 12;

  // Counters from /proc/diskstats.
  message DiskStat {
    optional string device_name = 1;
    optional uint64 read_sectors = 2;
    optional uint64 read_time_ms = 3;
    optional uint64 write_sectors = 4;
    optional uint64 write_time_ms = 5;
    optional uint64 discard_sectors = 6;
    optional uint64 discard_time_ms = 7;
    optional uint64 flush_count = 8;
    optional uint64 flush_time_ms = 9;
  }
  // One entry per disk device.
  repeated DiskStat disk_stat = 13;

  // Reading from /proc/pressure/*.
  message PsiSample {
    // Type of resource that may have exhibited pressure stalls.
    //    * _SOME indicates some resource tasks stalled.
    //    * _FULL indicates all non-idle resource tasks stalled simultaneously.
    enum PsiResource {
      PSI_RESOURCE_UNSPECIFIED = 0;
      PSI_RESOURCE_CPU_SOME = 1;
      PSI_RESOURCE_CPU_FULL = 2;
      PSI_RESOURCE_IO_SOME = 3;
      PSI_RESOURCE_IO_FULL = 4;
      PSI_RESOURCE_MEMORY_SOME = 5;
      PSI_RESOURCE_MEMORY_FULL = 6;
    }
    optional PsiResource resource = 1;

    // Total absolute stall time (in nanos) for a given resource.
    // While PSI readings are in micros, we store in nanos for consistency with
    // most other time-based counters.
    optional uint64 total_ns = 2;

    // Note that /proc/pressure/* exposes historical average utilization values
    // (as a %), but we don't yet sample those. They could easily be added as
    // additional fields should the total stall time readings be insufficient.
  }
  // One entry per PsiResource type.
  repeated PsiSample psi = 14;

  // Reading from /sys/class/thermal/*.
  message ThermalZone {
    optional string name = 1;
    optional uint64 temp = 2;
    optional string type = 3;
  }
  repeated ThermalZone thermal_zone = 15;

  // Reading from /sys/devices/system/cpu/cpu*/cpuidle/state*.
  message CpuIdleStateEntry {
    // Name of the idle state, e.g. C1-C10
    optional string state = 1;
    optional uint64 duration_us = 2;
  }
  message CpuIdleState {
    optional uint32 cpu_id = 1;
    repeated CpuIdleStateEntry cpuidle_state_entry = 2;
  }
  repeated CpuIdleState cpuidle_state = 16;

  // Read GPU frequency info on Intel/AMD devices.
  repeated uint64 gpufreq_mhz = 17;

  // Reading from /proc/slabinfo.
  message SlabInfo {
    optional string name = 1;
    optional uint32 pages_per_slab = 2;
    optional uint32 num_slabs = 3;
  }
  repeated SlabInfo slab_info = 18;
}
