From 325ae88232cc693ef57478c049425be5da7766d8 Mon Sep 17 00:00:00 2001 From: zhilan Date: Wed, 7 Jun 2023 02:30:08 +0000 Subject: [PATCH 1/3] podmem to unity --- source/lib/internal/ebpf/coolbpf | 2 +- .../unity/collector/native/plugincffi.lua | 3 + .../monitor/unity/collector/plugin/Makefile | 2 +- .../unity/collector/plugin/podmem/Makefile | 21 + .../unity/collector/plugin/podmem/btfparse.h | 38 ++ .../unity/collector/plugin/podmem/cache.h | 103 ++++ .../unity/collector/plugin/podmem/memcg.cpp | 495 +++++++++++++++++ .../unity/collector/plugin/podmem/memcg.h | 33 ++ .../unity/collector/plugin/podmem/memread.cpp | 525 ++++++++++++++++++ .../unity/collector/plugin/podmem/offset.cpp | 225 ++++++++ .../unity/collector/podMan/podsAll.lua | 34 ++ .../tools/monitor/unity/collector/podmem.lua | 111 ++++ 12 files changed, 1590 insertions(+), 2 deletions(-) create mode 100644 source/tools/monitor/unity/collector/plugin/podmem/Makefile create mode 100644 source/tools/monitor/unity/collector/plugin/podmem/btfparse.h create mode 100644 source/tools/monitor/unity/collector/plugin/podmem/cache.h create mode 100644 source/tools/monitor/unity/collector/plugin/podmem/memcg.cpp create mode 100644 source/tools/monitor/unity/collector/plugin/podmem/memcg.h create mode 100644 source/tools/monitor/unity/collector/plugin/podmem/memread.cpp create mode 100644 source/tools/monitor/unity/collector/plugin/podmem/offset.cpp create mode 100644 source/tools/monitor/unity/collector/podmem.lua diff --git a/source/lib/internal/ebpf/coolbpf b/source/lib/internal/ebpf/coolbpf index ae774b80..d0fabf82 160000 --- a/source/lib/internal/ebpf/coolbpf +++ b/source/lib/internal/ebpf/coolbpf @@ -1 +1 @@ -Subproject commit ae774b805b2185fcbfafb71457ad1e37065466ff +Subproject commit d0fabf821d2d8eb9d27da8eefd4797dc181cc92b diff --git a/source/tools/monitor/unity/collector/native/plugincffi.lua b/source/tools/monitor/unity/collector/native/plugincffi.lua index 037ba320..9c23c9e3 100644 --- a/source/tools/monitor/unity/collector/native/plugincffi.lua +++ b/source/tools/monitor/unity/collector/native/plugincffi.lua @@ -39,6 +39,9 @@ void deinit(void); void free(void *p); int setns(int fd, int nstype); +char* scanall(); +int monitor_init(const char* proc); +void monitor_exit(); ]] return ffi diff --git a/source/tools/monitor/unity/collector/plugin/Makefile b/source/tools/monitor/unity/collector/plugin/Makefile index 20ba7476..82983f6a 100644 --- a/source/tools/monitor/unity/collector/plugin/Makefile +++ b/source/tools/monitor/unity/collector/plugin/Makefile @@ -5,7 +5,7 @@ OBJS := proto_sender.o LIB := libproto_sender.a #DEPMOD=sample threads kmsg proc_schedstat proc_loadavg unity_nosched unity_irqoff cpudist cpu_bled net_health net_retrans netlink cpufreq gpuinfo pmu_events virtout sum_retrans virtiostat -DEPMOD=sample threads kmsg proc_schedstat proc_loadavg unity_irqoff cpudist cpu_bled net_health net_retrans netlink cpufreq gpuinfo pmu_events virtout sum_retrans virtiostat +DEPMOD=sample threads kmsg proc_schedstat proc_loadavg unity_irqoff cpudist cpu_bled net_health net_retrans netlink cpufreq gpuinfo pmu_events virtout sum_retrans virtiostat podmem all: $(LIB) $(DEPMOD) diff --git a/source/tools/monitor/unity/collector/plugin/podmem/Makefile b/source/tools/monitor/unity/collector/plugin/podmem/Makefile new file mode 100644 index 00000000..ee676b26 --- /dev/null +++ b/source/tools/monitor/unity/collector/plugin/podmem/Makefile @@ -0,0 +1,21 @@ +CC := g++ +CFLAG := -g -fpic +LDFLAG := -g -fpic -shared -static-libstdc++ +OBJS := memcg.o offset.o memread.o +SO := libpodmem.so +LIBS += -L ${OBJ_LIB_PATH}/lib -lcoolbpf -lelf -lz -lpthread +LDFLAG += -Wall $(LIBS) + +all: $(SO) install + +%.o: %.cpp + $(CC) -c $< -o $@ $(CFLAG) + +$(SO): $(OBJS) + $(CC) -o $@ $(OBJS) $(LDFLAG) + +install: $(SO) + cp $(SO) ../../native/ + +clean: + rm -f $(SO) $(OBJS) diff --git a/source/tools/monitor/unity/collector/plugin/podmem/btfparse.h b/source/tools/monitor/unity/collector/plugin/podmem/btfparse.h new file mode 100644 index 00000000..3a586d0f --- /dev/null +++ b/source/tools/monitor/unity/collector/plugin/podmem/btfparse.h @@ -0,0 +1,38 @@ + + +#ifndef __BTF_PARSE_H +#define __BTF_PARSE_H + + + +/** + * btf_load: load btf from btf_custom_path + * + * @btf_custom_path: path of btf file + */ +struct btf *btf_load(char *btf_custom_path); +typedef unsigned int uint32_t; + +struct member_attribute +{ + uint32_t size; // size of structure's member + uint32_t real_size; // real_size mean + uint32_t offset; // offset of member in strucutre +}; + +/** + * btf_find_struct_member - find struct btfid by structure's name + * + * @btf: + * @struct_name: name of struct + * @member_name: name of structure's member + * @return: NULL mean error, get error number from errno. + * + * Note: Remember to free pointer of struct member_attribute + */ +struct member_attribute *btf_find_struct_member(struct btf *btf, char *struct_name, char *member_name); +void btf__free(struct btf *btf); + + +#endif + diff --git a/source/tools/monitor/unity/collector/plugin/podmem/cache.h b/source/tools/monitor/unity/collector/plugin/podmem/cache.h new file mode 100644 index 00000000..8b8c14bc --- /dev/null +++ b/source/tools/monitor/unity/collector/plugin/podmem/cache.h @@ -0,0 +1,103 @@ +/* + * Page scan tool + */ +#ifndef _PAGESCAN_UTIL_H +#define _PAGESCAN_UTIL_H + +#include +#include +#include +#include +#include +#include + + +extern unsigned long page_shift; +#define MAX_ORDER 11 +#define PAGE_SIZE (1UL << page_shift) +#define HUGE_SIZE (PAGE_SIZE * HUGE_PAGE_NR) +#define BUFF_MAX 4096 +#define SIZE_KB (1UL << 10) +#define SIZE_MB (1UL << 20) +#define MAX_KCORE_ELF_HEADER_SIZE 32768 + + +#ifdef DEBUG +#define LOG_DEBUG(...) fprintf(stderr, __VA_ARGS__) +#else +#define LOG_DEBUG(...) do { } while (0) +#endif /* DEBUG */ + +#define LOG_INFO(...) fprintf(stdout, __VA_ARGS__) +#define LOG_WARN(...) fprintf(stderr, __VA_ARGS__) +#define LOG_ERROR(...) fprintf(stderr, __VA_ARGS__) + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +extern unsigned long vmemmap_base; +extern unsigned long page_offset_base; +extern uint64_t g_max_phy_addr; +extern unsigned long memstart_addr; +#define PAGE_STRUCT_SIZE 64 + +#ifdef __aarch64__ /*arm arch*/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) /*kernel 510*/ +#define VA_BITS (48) +#define SZ_2M 0x00200000 +#define STRUCT_PAGE_MAX_SHIFT (6) +#define VA_BITS_MIN (48) + +#define _PAGE_END(va) (-((unsigned long )(1) << ((va) - 1))) +#define _PAGE_OFFSET(va) (-((unsigned long )(1) << (va))) +#define PAGE_OFFSET (_PAGE_OFFSET(VA_BITS)) +#define VMEMMAP_SIZE ((_PAGE_END(VA_BITS_MIN) - PAGE_OFFSET) \ + >> (page_shift - STRUCT_PAGE_MAX_SHIFT)) +#define PHYS_OFFSET (memstart_addr) +#define VMEMMAP_START (-VMEMMAP_SIZE - SZ_2M) +#define vmemmap (VMEMMAP_START - (memstart_addr >> page_shift)*PAGE_STRUCT_SIZE) + +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 9)/*kernel 419*/ +#define VA_BITS (48) +#define VA_START ((unsigned long )(0xffffffffffffffff) - \ + ((unsigned long )(1) << VA_BITS) + 1) +#define PAGE_OFFSET ((unsigned long )(0xffffffffffffffff) - \ + ((unsigned long )(1) << (VA_BITS - 1)) + 1) +#define STRUCT_PAGE_MAX_SHIFT (6) +#define VMEMMAP_SIZE ((unsigned long )(1) << (VA_BITS - page_shift - 1 + STRUCT_PAGE_MAX_SHIFT)) +#define VMEMMAP_START (PAGE_OFFSET - VMEMMAP_SIZE) +#define vmemmap (VMEMMAP_START - (memstart_addr >> page_shift)*PAGE_STRUCT_SIZE) + +#else /*others*/ +#define SZ_64K 0x00010000 +#define PAGE_OFFSET (unsigned long )(0xffffffc000000000) +#define VMALLOC_END (PAGE_OFFSET - (unsigned long)(0x400000000) - SZ_64K) +#define vmemmap ((struct page *)(VMALLOC_END + SZ_64K)) + +#endif /*end to check ver, arm arch*/ +#define PFN_TO_VIRT(pfn) (((unsigned long)((pfn) - PHYS_OFFSET) | PAGE_OFFSET) + ((pfn) << page_shift)) +#define PFN_TO_PAGE(pfn) (vmemmap + (pfn) * PAGE_STRUCT_SIZE) +#define is_kvaddr(kvaddr) (!!(kvaddr >= PAGE_OFFSET)) +#else /*x86 arch*/ + +#define PFN_TO_VIRT(pfn) (page_offset_base + ((pfn) << page_shift)) +#define PFN_TO_PAGE(pfn) (vmemmap_base + (pfn) * PAGE_STRUCT_SIZE) +#define is_kvaddr(kvaddr) (!!(kvaddr >= page_offset_base)) +#endif +#define max_pfn (g_max_phy_addr>>12) + +struct options { + bool podmem; + bool fullscan; + char *cgroupfile; + char *cgroup; + unsigned int rate; + unsigned int top; +}; + +#define KPF_SIZE 8 +ssize_t kpageflags_read(void *buf, size_t count, off_t offset); +ssize_t kpagecgroup_read(void *buf, size_t count, off_t offset); +uintptr_t lookup_kernel_symbol(const char *symbol_name); +ssize_t kcore_readmem(unsigned long kvaddr, void *buf, ssize_t size); +#endif /* _PAGESCAN_UTIL_H */ diff --git a/source/tools/monitor/unity/collector/plugin/podmem/memcg.cpp b/source/tools/monitor/unity/collector/plugin/podmem/memcg.cpp new file mode 100644 index 00000000..df078aa3 --- /dev/null +++ b/source/tools/monitor/unity/collector/plugin/podmem/memcg.cpp @@ -0,0 +1,495 @@ +#include +#include +#include +#include +#include +#include "cache.h" +#include "memcg.h" +#include "btfparse.h" + +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +#ifndef KPF_RESERVED +#define KPF_RESERVED 32 +#endif + +#ifndef KPF_IDLE +#define KPF_IDLE (25) +#endif + +#define MAX_BIT (26) + + +map files; +map inodes; +static bool full_scan; +static unsigned int scan_rate = 4; +struct file_info { + char filename[256]; + unsigned long inode; + unsigned long cached; + unsigned long cgcached; + unsigned long size; + unsigned long active; + unsigned long dirty; + unsigned long inactive; + unsigned long cinode; + int shmem; + int del; +}; +extern struct member_attribute *get_offset(string struct_name, string member_name); + +static int prepend(char **buffer, int *buflen, const char *str, int namelen, int off) +{ + *buflen -= namelen + off; + if (*buflen < 0) + return -1; + *buffer -= namelen + off; + if (off) + **buffer = '/'; + memcpy(*buffer + off, str, namelen); + return 0; +} + +static unsigned long inode2mount(unsigned long inode) +{ + unsigned long sb; + unsigned long mount; + struct member_attribute *att; + att = get_offset("inode", "i_sb"); + if (!att) { + return 0; + } + kcore_readmem(inode + att->offset, &sb, sizeof(sb)); + att = get_offset("super_block", "s_mounts"); + if (!att) { + return 0; + } + kcore_readmem(sb+ att->offset, &mount, sizeof(mount)); + att = get_offset("mount", "mnt_instance"); + if (!att) { + return 0; + } + mount -= att->offset; + return mount; +} + +static int get_filename(unsigned long dentry, char *filename, int len) +{ + unsigned long parent; + char name[4096] = {0}; + char tmp[4096] = {0}; + char *end = tmp + 4095; + int buflen = 4095; + struct qstr str; + struct member_attribute *att; + while (dentry) { + + memset(name, 0, 128); + att = get_offset("dentry", "d_parent"); + kcore_readmem(dentry+att->offset, &parent, sizeof(parent)); + att = get_offset("dentry", "d_name"); + if (!att) { + return 0; + } + kcore_readmem(dentry + att->offset, &str, sizeof(str)); + if (parent == dentry || str.len<=0) + break; + dentry = parent; + if (str.len > 4096) + str.len = 4096; + + kcore_readmem((unsigned long)str.name, name, str.len); + prepend(&end, &buflen, name, strlen(name), 1); + } + strncpy(filename, end, len); + return 0; +} + +/* + * pfn: page pfn + * cinode: cgroup inode + */ +static int get_dentry(unsigned long pfn, unsigned long cinode, int active, int shmem, int dirty) +{ + map::iterator iter; + unsigned long page = PFN_TO_PAGE(pfn); + unsigned long map = 0; + unsigned long cached = 0; + unsigned long inode = 0; + unsigned long inode_dentry =0; + unsigned long dentry_first = 0; + unsigned long hdentry = 0; + unsigned long pdentry = 0; + unsigned long mount = 0; + char filename[1024] = {0}; + char tmp[4096] = {0}; + char *end = tmp + 4095; + int buflen = 4095; + unsigned long i_ino; + unsigned long i_size; + struct file_info *info; + int del = 0; + struct member_attribute *att; + att = get_offset("page", "mapping"); + if (!att) { + return 0; + } + + kcore_readmem(page + att->offset, &map, sizeof(map)); + if (!is_kvaddr(map)) + return 0; + att = get_offset("address_space", "nrpages"); + if (!att) { + return 0; + } + kcore_readmem(map + att->offset, &cached, sizeof(cached)); + /* skip file cache < 100K */ + if (cached*4 < 100) + return 0; + + att = get_offset("address_space", "host"); + if (!att) { + return 0; + } + kcore_readmem(map + att->offset, &inode, sizeof(inode)); + att = get_offset("inode", "i_ino"); + if (!att) { + return 0; + } + kcore_readmem(inode + att->offset, &i_ino, sizeof(i_ino)); + iter = files.find(i_ino); + if (iter != files.end()) { + info = iter->second; + if (active) { + info->active += 1; + }else { + info->inactive += 1; + } + if (dirty) { + info->dirty += 1; + } + + if (info->cinode == cinode) + info->cgcached++; + return 0; + } + att = get_offset("inode", "i_size"); + if (!att) { + return 0; + } + kcore_readmem(inode + att->offset, &i_size, sizeof(i_size)); + + mount = inode2mount(inode); + att = get_offset("inode","i_dentry"); + if (!att) { + return 0; + } + kcore_readmem(inode + att->offset, &inode_dentry, sizeof(inode)); + if (!is_kvaddr(inode_dentry)) + return 0; + att = get_offset("dentry", "d_alias"); + if (!att) { + att = get_offset("dentry", "d_u"); + if (!att) + return 0; + } + + dentry_first = inode_dentry - att->offset; + memset(filename, 0, 1024); + att = get_offset("dentry", "d_parent"); + if (!att) { + return 0; + } + kcore_readmem(dentry_first+att->offset, &pdentry, sizeof(pdentry)); + att = get_offset("dentry", "d_hash"); + if (!att) { + return 0; + } + kcore_readmem(dentry_first+att->offset + sizeof(void*), &hdentry, sizeof(hdentry)); + if ((dentry_first != pdentry) && !hdentry) + del = 1; + do { + unsigned long mount_parent = 0; + unsigned long mount_dentry = 0; + int len = 0; + int ret = 0; + + get_filename(dentry_first, filename, 1024); + len = strlen(filename); + if (len <=0 || ((len == 1) && (filename[0] == '/'))) + break; + + prepend(&end, &buflen, filename, strlen(filename), 0); + att = get_offset("mount", "mnt_parent"); + if (!att) { + return 0; + } + ret = kcore_readmem(mount + att->offset, &mount_parent , sizeof(mount_parent)); + if (ret != sizeof(mount_parent)) + break; + att = get_offset("mount", "mnt_mountpoint"); + if (!att) { + return 0; + } + kcore_readmem(mount+ att->offset, &mount_dentry, sizeof(mount_dentry)); + if (mount_parent == mount || mount_dentry==dentry_first) + break; + dentry_first = mount_dentry; + mount = mount_parent; + } while(true); + + if (buflen >= 4092) + return 0; + info = (struct file_info *)malloc(sizeof(struct file_info)); + if (!info) { + printf("alloc file info error \n"); + return 0; + } + memset(info, 0, sizeof(sizeof(struct file_info))); + info->inode = i_ino; + info->shmem = shmem; + info->cached = cached*4; + info->cgcached = 1; + info->active = 0; + info->dirty = 0; + info->inactive = 0; + info->del = del; + if (active) + info->active = 1; + else + info->inactive = 1; + if (dirty) + info->dirty = 1; + + info->cinode = cinode; + info->size = i_size>>10; + strncpy(info->filename, end, sizeof(info->filename) - 2); + info->filename[sizeof(info->filename) -1] = '0'; + files[i_ino] = info; + return 0; +} + +unsigned long get_cgroup_inode(unsigned long pfn) +{ + unsigned long ino; + int ret = 0; + + ret = kpagecgroup_read(&ino, sizeof(ino), pfn*sizeof(ino)); + if (ret != sizeof(ino)) { + return 0; + } + return ino; +} + +int check_cgroup_inode(unsigned long inode) +{ + return (full_scan||(inodes.find(inode)!=inodes.end())); +} + +bool cached_cmp(const pair& a, const pair& b) { + struct file_info *a_file = a.second; + struct file_info *b_file = b.second; + if (!a_file || !b_file) + return 1; + return a_file->cached > b_file->cached; +} + +static int output_file_cached_string(unsigned int top, char *res) +{ + map::iterator iter; + vector< pair > vec(files.begin(), files.end()); + struct file_info *info; + int size = 0; + + for (iter = files.begin(); iter != files.end(); ++iter) { + info = (*iter).second; + if (!info) { + continue; + } + } + sort(vec.begin(), vec.end(), cached_cmp); + + for (int i = 0; i < vec.size(); ++i) { + info = vec[i].second; + if (!info) { + continue; + } + //printf("inode=%lu file=%s cached=%lu size=%lu cinode=%lu active=%lu inactive=%lu shmem=%d \ + // delete=%d cgcached=%lu dirty=%lu\n", info->inode, info->filename, info->cached, info->size,\ + // info->cinode, info->active*4, info->inactive*4, info->shmem, info->del, info->cgcached*4, info->dirty*4); + + if (i <= top - 1) + size += sprintf(res + size, "cinode=%lu cached=%lu size=%lu file=%s\n",info->cinode,info->cached, info->size,info->filename); + free(info); + } + files.clear(); + return 0; +} +static int output_file_cached(unsigned int top) +{ + map::iterator iter; + vector< pair > vec(files.begin(), files.end()); + struct file_info *info; + + for (iter = files.begin(); iter != files.end(); ++iter) { + info = (*iter).second; + if (!info) { + continue; + } + } + sort(vec.begin(), vec.end(), cached_cmp); + + for (int i = 0; i < vec.size(); ++i) { + info = vec[i].second; + if (!info) { + continue; + } + printf("inode=%lu file=%s cached=%lu size=%lu cinode=%lu active=%lu inactive=%lu shmem=%d \ + delete=%d cgcached=%lu dirty=%lu\n", info->inode, info->filename, info->cached, info->size,\ + info->cinode, info->active*4, info->inactive*4, info->shmem, info->del, info->cgcached*4, info->dirty*4); + + //size += sprintf(res + size, "cinode=%lu cached=%lu size=%lu file=%s\n", info->cinode,info->cached, info->size,info->filename); + free(info); + if (i >= top - 1) + break; + } + return 0; +} + + +int scan_pageflags_nooutput(struct options *opt, char *res) +{ + unsigned long pageflag; + unsigned long pfn = 0; + unsigned long inode = 0; + int active = 0; + int dirty = 0; + int shmem = 0; + + if (opt->rate != 0) { + scan_rate = opt->rate; + } + full_scan = opt->fullscan; + while (1) { + int ret = 0; + pageflag = 0; + + pfn += scan_rate ;/* skip 2M*/ + + if (pfn > max_pfn) + break; + ret = kpageflags_read(&pageflag, sizeof(pageflag), sizeof(pageflag)*pfn); + if (ret != sizeof(pageflag)) { + break; + } + if (pageflag & (1 << KPF_NOPAGE) || !pageflag) + continue; + + if ((pageflag & (1<> KPF_RESERVED) & 0x1)) + continue; + if (pageflag & (1 << KPF_ANON)) + continue; + + active = !!((1<top, res); + return 0; +} + +int scan_pageflags(struct options *opt) +{ + unsigned long pageflag; + unsigned long pfn = 0; + unsigned long inode = 0; + int active = 0; + int dirty = 0; + int shmem = 0; + + if (opt->rate != 0) { + scan_rate = opt->rate; + } + full_scan = opt->fullscan; + while (1) { + int ret = 0; + pageflag = 0; + + pfn += scan_rate ;/* skip 2M*/ + + if (pfn > max_pfn) + break; + ret = kpageflags_read(&pageflag, sizeof(pageflag), sizeof(pageflag)*pfn); + if (ret != sizeof(pageflag)) { + break; + } + if (pageflag & (1 << KPF_NOPAGE) || !pageflag) + continue; + + if ((pageflag & (1<> KPF_RESERVED) & 0x1)) + continue; + if (pageflag & (1 << KPF_ANON)) + continue; + + active = !!((1<top); + return 0; +} + +int memcg_cgroup_path(const char *cgrouppath) +{ + struct stat st; + if (access(cgrouppath, F_OK)) { + return 0; + } + + stat(cgrouppath, &st); + inodes[st.st_ino] = 1; + return 0; +} + +int memcg_cgroup_file(const char *cgroupfile) +{ + ifstream filename(cgroupfile); + string cgroup; + int count = 0; + + if (!filename) { + printf("open %s failed\n", cgroupfile); + return 0; + } + + while (getline(filename, cgroup)) + { + memcg_cgroup_path(cgroup.c_str()); + count ++; + } + filename.close(); + return count; +} diff --git a/source/tools/monitor/unity/collector/plugin/podmem/memcg.h b/source/tools/monitor/unity/collector/plugin/podmem/memcg.h new file mode 100644 index 00000000..b5556824 --- /dev/null +++ b/source/tools/monitor/unity/collector/plugin/podmem/memcg.h @@ -0,0 +1,33 @@ +#ifndef __POD__ +#define __POD__ + +#include +#include +#include +using namespace std; + +#define SIZE (32) +#define NAME (4096) + +/*file */ +struct fileinfo { + char name[NAME]; + unsigned long cached; + unsigned long size; + unsigned long inode; + unsigned long ino; +}; +typedef unsigned int u32; +typedef unsigned long long u64; + +struct qstr { + union { + struct { + u32 hash; + u32 len; + }; + u64 hash_len; + }; + const unsigned char *name; +}; +#endif diff --git a/source/tools/monitor/unity/collector/plugin/podmem/memread.cpp b/source/tools/monitor/unity/collector/plugin/podmem/memread.cpp new file mode 100644 index 00000000..f9eb4e63 --- /dev/null +++ b/source/tools/monitor/unity/collector/plugin/podmem/memread.cpp @@ -0,0 +1,525 @@ +/* + * pod memory tool + */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cache.h" +#define MAX_CGROUP 256 + +extern int scan_pageflags(struct options * opt); +extern int scan_pageflags_nooutput(struct options * opt,char *res); +extern int memcg_cgroup_file(const char *cgroupfile); +extern int memcg_cgroup_path(const char *cgrouppath); +extern int offset_init(void); +extern int sym_uninit(void); + +extern "C" { +char* scanall(); +int monitor_init(const char* proc); +void monitor_exit(); +} + +struct options opt = {0}; + +struct proc_kcore_data { + unsigned int flags; + unsigned int segments; + char *elf_header; + size_t header_size; + Elf64_Phdr *load64; + Elf64_Phdr *notes64; + Elf32_Phdr *load32; + Elf32_Phdr *notes32; + void *vmcoreinfo; + unsigned int size_vmcoreinfo; +}; + +static struct proc_kcore_data proc_kcore_data = { 0 }; +static struct proc_kcore_data *pkd = &proc_kcore_data; + +static int kcore_fd = 0; +static int kpageflags_fd = 0; +static int kpagecgroup_fd = 0; +uint64_t g_max_phy_addr; + + +/* + * kernel vmemmap_base page_offset_base + * 3.10 0xffffea0000000000UL 0xffff880000000000UL + * 4.9 0xffffea0000000000UL 0xffff880000000000UL + * 4.19 0xffffea0000000000UL 0xffff888000000000UL + * + * We use default vmemmap_base and page_offset_base values on kernel 4.9, + * which is the same on kernel 3.10, and reassign these two values on + * kernel 4.19 due to kaslr, by kcore. + */ +unsigned long vmemmap_base = 0xffffea0000000000UL; +unsigned long page_offset_base = 0xffff880000000000UL; +unsigned long memstart_addr = 0x0; +unsigned long page_shift = 0; + +/* + * Routines of kpageflags, i.e., /proc/kpageflags + */ +ssize_t kpageflags_read(void *buf, size_t count, off_t offset) +{ + return pread(kpageflags_fd, buf, count, offset); +} + +ssize_t kpagecgroup_read(void *buf, size_t count, off_t offset) +{ + ssize_t ret = 0; + if (kpagecgroup_fd > 0) + ret = pread(kpagecgroup_fd, buf, count, offset); + + return ret; +} + +/* + * Routines of kcore, i.e., /proc/kcore + */ +uintptr_t lookup_kernel_symbol(const char *symbol_name, const char *proc) +{ + std::string tmp(proc); + tmp += "/proc/kallsyms"; + const char *kallsyms_file = tmp.c_str(); + FILE *fp; + char line[BUFF_MAX]; + char *pos; + uintptr_t addr = -1UL; + + fp = fopen(kallsyms_file, "r"); + if (fp == NULL) { + perror("fopen: /proc/kallsyms"); + return -1; + } + + while (fgets(line, BUFF_MAX, fp)) { + if ((pos = strstr(line, symbol_name)) == NULL) + continue; + + /* Remove trailing newline */ + line[strcspn(line, "\n")] = '\0'; + + /* Exact match */ + if (pos == line || !isspace(*(pos - 1))) + continue; + if (!strcmp(pos, symbol_name)) { + addr = strtoul(line, NULL, 16); + break; + } + } + + if (addr == -1UL) + LOG_ERROR("failed to lookup symbol: %s\n", symbol_name); + + fclose(fp); + return addr; +} + +static int kcore_elf_init(void) +{ + Elf64_Ehdr *elf64; + Elf64_Phdr *load64; + Elf64_Phdr *notes64; + char eheader[MAX_KCORE_ELF_HEADER_SIZE]; + size_t load_size, notes_size; + + if (read(kcore_fd, eheader, MAX_KCORE_ELF_HEADER_SIZE) != + MAX_KCORE_ELF_HEADER_SIZE) { + perror("read: /proc/kcore ELF header"); + return -1; + } + + elf64 = (Elf64_Ehdr *)&eheader[0]; + notes64 = (Elf64_Phdr *)&eheader[sizeof(Elf64_Ehdr)]; + load64 = (Elf64_Phdr *)&eheader[sizeof(Elf64_Ehdr) + + sizeof(Elf64_Phdr)]; + + pkd->segments = elf64->e_phnum - 1; + + notes_size = load_size = 0; + if (notes64->p_type == PT_NOTE) + notes_size = notes64->p_offset + notes64->p_filesz; + if (notes64->p_type == PT_LOAD) + load_size = (unsigned long)(load64+(elf64->e_phnum)) - + (unsigned long)elf64; + + pkd->header_size = MAX(notes_size, load_size); + if (!pkd->header_size) + pkd->header_size = MAX_KCORE_ELF_HEADER_SIZE; + + if ((pkd->elf_header = (char *)malloc(pkd->header_size)) == NULL) { + perror("malloc: /proc/kcore ELF header"); + return -1; + } + + memcpy(&pkd->elf_header[0], &eheader[0], pkd->header_size); + pkd->notes64 = (Elf64_Phdr *)&pkd->elf_header[sizeof(Elf64_Ehdr)]; + pkd->load64 = (Elf64_Phdr *)&pkd->elf_header[sizeof(Elf64_Ehdr) + + sizeof(Elf64_Phdr)]; + + return 0; +} + +static int kcore_init(const char* proc) +{ + unsigned long vmemmap_symbol_addr; + unsigned long page_offset_symbol_addr; + unsigned long memstart_addr_addr; + std::string tmp(proc); + tmp += "/proc/kcore"; + int size; + + if ((kcore_fd = open(tmp.c_str(), O_RDONLY)) < 0) { + perror("open: /proc/kcore"); + return -1; + } + + if (kcore_elf_init()) + goto failed; + + vmemmap_symbol_addr = lookup_kernel_symbol("vmemmap_base",proc); + if (vmemmap_symbol_addr == (unsigned long )-1) { + LOG_WARN("continue to use default vmemmap_base: 0x%lx\n", + vmemmap_base); + } else { + size = kcore_readmem(vmemmap_symbol_addr, &vmemmap_base, 8); + if (size < 8) + goto failed; + } + + page_offset_symbol_addr = lookup_kernel_symbol("page_offset_base", proc); + if (page_offset_symbol_addr == (unsigned long)-1) { + LOG_WARN("continue to use default page_offset_base: 0x%lx\n", + page_offset_base); + } else { + size = kcore_readmem(page_offset_symbol_addr, &page_offset_base, 8); + if (size < 8) + goto failed; + } + + memstart_addr_addr = lookup_kernel_symbol("memstart_addr",proc); + if (memstart_addr_addr == (unsigned long)-1) { + LOG_WARN("continue to use default memstart_addr_base: 0x%lx\n", + memstart_addr); + } else { + size = kcore_readmem(memstart_addr_addr, &memstart_addr, 8); + if (size < 8) + goto failed; + } + return 0; + +failed: + close(kcore_fd); + return -1; +} + +/* + * We may accidentally access invalid pfns on some kernels + * like 4.9, due to known bugs. Just skip it. + */ +ssize_t kcore_readmem(unsigned long kvaddr, void *buf, ssize_t size) +{ + Elf64_Phdr *lp64; + unsigned long offset = -1UL; + ssize_t read_size; + unsigned int i; + + for (i = 0; i < pkd->segments; i++) { + lp64 = pkd->load64 + i; + if ((kvaddr >= lp64->p_vaddr) && + (kvaddr < (lp64->p_vaddr + lp64->p_memsz))) { + offset = (off_t)(kvaddr - lp64->p_vaddr) + + (off_t)lp64->p_offset; + break; + } + } + if (i == pkd->segments) { + for (i = 0; i < pkd->segments; i++) { + lp64 = pkd->load64 + i; + LOG_DEBUG("%2d: [0x%lx, 0x%lx)\n", i, lp64->p_vaddr, + lp64->p_vaddr + lp64->p_memsz); + } + //printf("invalid kvaddr 0x%lx\n", kvaddr); + goto failed; + } + + if (lseek(kcore_fd, offset, SEEK_SET) < 0) { + perror("lseek: /proc/kcore"); + goto failed; + } + + read_size = read(kcore_fd, buf, size); + if (read_size < size) { + perror("read: /proc/kcore"); + goto failed; + } + + return read_size; + +failed: + return -1; +} + +static void kcore_exit(void) +{ + if (pkd->elf_header) + free(pkd->elf_header); + if (kcore_fd > 0) + close(kcore_fd); +} + + +static uint64_t get_max_phy_addr(const char *proc) +{ + std::string iofile(proc); + iofile += "/proc/iomem"; + const char *iomem_file = iofile.c_str(); + printf("%s\n",iomem_file); + FILE *fp = NULL; + char line[BUFF_MAX], *pos, *end = NULL; + uint64_t max_phy_addr = 0; + + fp = fopen(iomem_file, "r"); + if (fp == NULL) { + perror("fopen: /proc/iomem"); + return 0ULL; + } + + while (fgets(line, BUFF_MAX, fp)) { + if (strstr(line, "System RAM") == NULL) + continue; + + pos = strchr(line, '-'); + if (pos == NULL) + break; + pos++; + + max_phy_addr = strtoull(pos, &end, 16); + if (end == NULL) { + perror("strtoull: max_phy_addr"); + max_phy_addr = 0; + break; + } + } + + fclose(fp); + return max_phy_addr; +} + +static int setup(const char* proc) +{ + std::string filename(proc); + std::string tmp; + g_max_phy_addr = get_max_phy_addr(proc); + if (g_max_phy_addr == 0ULL) { + g_max_phy_addr = 64 * 1024 * 1024 * 1024; + LOG_ERROR("failed to get max physical address\n"); + } + LOG_DEBUG("max physical address = %#lx\n", g_max_phy_addr); + + tmp = filename+"/proc/kpageflags"; + kpageflags_fd = open(tmp.c_str(), O_RDONLY); + if (kpageflags_fd < 0) { + perror("open: /proc/kpageflags"); + return -1; + } + tmp = filename+"/proc/kpagecgroup"; + kpagecgroup_fd = open(tmp.c_str(), O_RDONLY); + if (kpagecgroup_fd < 0) { + perror("open: /proc/kpagecgroup"); + } + if (kcore_init(proc) < 0) { + LOG_ERROR("failed to init kcore\n"); + return -1; + } + + return offset_init(); +} + +static void cleanup(void) +{ + if (kpageflags_fd > 0) + close(kpageflags_fd); + + if (kpagecgroup_fd > 0) { + close(kpagecgroup_fd); + } + sym_uninit(); + kcore_exit(); +} + +static int get_pageshift() +{ + int page_size = getpagesize(); + + if(page_size <= 0 ) + { + LOG_ERROR("failed to get page size\n"); + return -1; + } + while (page_size > 1) { + page_size >>= 1; + page_shift++; + } + return 0; +} + +static void show_usage(void) +{ + LOG_INFO("Usage: %s [OPTIONS]\n" + "\n" + " -h, --help display this help and exit\n" + "\n" + "Supported options:\n" + " -m, pod cache tools \n" + "\n" + ); +} + +int monitor_init(const char* proc) +{ + int ret = get_pageshift(); + if (ret != 0) { + printf("failed to page shift\n"); + return ret; + } + ret = setup(proc); + if (ret != 0) { + printf("failed to setup\n"); + return ret; + } + return 0; +} + +void monitor_exit() +{ + cleanup(); +} + +char* scanall() +{ + const char *filename="/tmp/.memcg.txt"; + char *outputres = NULL; + + opt.rate = 100; + opt.top = 10; + int count = memcg_cgroup_file(filename); + if (count < 0) + return NULL; + count = (count < 0 || count>MAX_CGROUP) ? MAX_CGROUP:count; + count = 350 * opt.top * count; + outputres = (char*)malloc(count); + memset(outputres,0,count); + + scan_pageflags_nooutput(&opt,outputres); + return outputres; +} +/* +int main(int argc, char *argv[]) +{ + int ch, ret; + + const char *sopt = "hmf:c:a:r:t:"; + const struct option lopt[] = { + {"help", 0, NULL, 'h'}, + {"podmem", 0, NULL, 'm'}, + {"file", 0, NULL, 'f'}, + {"cgroup", 0, NULL, 'c'}, + {"all", 0, NULL, 'a'}, + {"rate", 0, NULL, 'r'}, + {"top", 0, NULL, 't'}, + { NULL, 0, NULL, 0 } + }; + opt.rate = 1; + opt.top = 10; + + while ((ch = getopt_long(argc, argv, sopt, lopt, &optind)) != -1) { + switch (ch) { + case 'h': + show_usage(); + return 0; + case 'm': + opt.podmem = true; + break; + case 'f': + opt.cgroupfile = strdup(optarg); + break; + case 'c': + opt.cgroup = strdup(optarg); + break; + case 'a': + opt.fullscan = atoi(optarg); + break; + case 't': + opt.top = atoi(optarg); + break; + case 'r': + opt.rate = atoi(optarg); + break; + case '?': + LOG_ERROR("try `%s --help' for more information\n", + argv[0]); + return -1; + } + } + + if (getuid()) { + LOG_ERROR("must be root\n"); + ret = -EPERM; + goto out; + } + + ret = get_pageshift(); + if (ret != 0) { + LOG_ERROR("failed to page shift\n"); + goto out; + } + + ret = setup(); + if (ret != 0) { + LOG_ERROR("failed to setup\n"); + goto out; + } + if (kpagecgroup_fd <= 0 && opt.podmem == true) { + opt.fullscan = 1; + } + if (opt.cgroupfile) { + memcg_cgroup_file(opt.cgroupfile); + } + + if (opt.cgroup) { + memcg_cgroup_path(opt.cgroup); + } + + if (opt.cgroupfile||opt.cgroup||opt.podmem) { + scan_pageflags(&opt); + } + + if (opt.cgroupfile) { + free(opt.cgroupfile); + } + if (opt.cgroup) { + free(opt.cgroup); + } + cleanup(); +out: + return ret; +}*/ diff --git a/source/tools/monitor/unity/collector/plugin/podmem/offset.cpp b/source/tools/monitor/unity/collector/plugin/podmem/offset.cpp new file mode 100644 index 00000000..fab42813 --- /dev/null +++ b/source/tools/monitor/unity/collector/plugin/podmem/offset.cpp @@ -0,0 +1,225 @@ +#include +#include +#include +#include +#include +#include +extern "C" { +#include "btfparse.h" +} + +#include +#include +using namespace std; +struct btf * handle; +#define LEN (128) + +map struct_offset; + +int sym_init(char *btf_name) +{ + handle = btf_load(btf_name); + + return !!(handle == NULL); +} + +int sym_uninit(void) +{ + btf__free(handle); + map::iterator iter; + struct member_attribute *info; + + for (iter = struct_offset.begin(); iter != struct_offset.end(); ++iter) { + info = (*iter).second; + if (info) { + free(info); + (*iter).second = NULL; + } + } + return 0; +} + +struct member_attribute *get_offset(string struct_name, string member_name) +{ + string index; + struct member_attribute *att; + map::iterator iter; + + index = struct_name + "_" + member_name; + iter = struct_offset.find(index); + if (iter != struct_offset.end()) { + return iter->second; + } + att = btf_find_struct_member(handle, (char*)struct_name.c_str(), (char*)member_name.c_str()); + if (!att) { + //printf("get %s error \n", index.c_str()); + return NULL; + } + //printf("%s:offset:%d, size:%d\n", index.c_str(),att->offset, att->size); + att->offset = att->offset/8; + struct_offset[index] = att; + return att; +} + +void stripWhiteSpace (string &str) +{ + if (str == "") + { + return; + } + + string::iterator cur_it; + cur_it = str.begin(); + + while (cur_it != str.end()) + { + if (((*cur_it) != '\t') && ((*cur_it) != ' ')) + { + break; + } + else + { + cur_it = str.erase (cur_it); + } + } + + cur_it = str.begin(); + + while (cur_it != str.end()) + { + if ((*cur_it) == '\n') + { + cur_it = str.erase (cur_it); + } + else + { + cur_it++; + } + } +} + +static int do_cmd(const char *cmd, char *result, int len) +{ + FILE *res; + char region[LEN] = {0}; + string str; + + res = popen(cmd, "r"); + if (res == NULL) { + printf("get region id failed\n"); + return -1; + } + + if (feof(res)) { + printf("cmd line end\n"); + return 0; + } + fgets(region, sizeof(region)-1, res); + str = region; + stripWhiteSpace(str); + /* skip \n */ + strncpy(result, str.c_str(), len - 1); + result[len - 1] = '\0'; + pclose(res); + return 0; +} + +static int download_btf(void) +{ + char region[LEN] = {0}; + char arch[LEN] = {0}; + char kernel[LEN] = {0}; + char dw[LEN+LEN] = {0}; + string sysak_path = "/boot"; + string timeout = "-internal"; + string cmd = "curl -s --connect-timeout 2 http://100.100.100.200/latest/meta-data/region-id 2>&1"; + + do_cmd(cmd.c_str(), region, LEN); + if (!strstr(region,"cn-")) { + strcpy(region, "cn-hangzhou"); + timeout = ""; + } + //printf("region:%s\n", region); + cmd = "uname -m"; + do_cmd(cmd.c_str(), arch, LEN); + //printf("arch:%s\n", arch); + + cmd = "uname -r"; + do_cmd(cmd.c_str(), kernel, LEN); + //printf("kernel:%s\n", kernel); + + if(getenv("SYSAK_WORK_PATH") != NULL) + { + sysak_path = getenv("SYSAK_WORK_PATH") ; + sysak_path += "/tools"; + } + + snprintf(dw, LEN + LEN + LEN, "wget -T 5 -t 2 -q -O %s/%s/vmlinux-%s https://sysom-cn-%s.oss-cn-%s%s.aliyuncs.com/home/hive/btf/%s/vmlinux-%s",sysak_path.c_str(), kernel, kernel, ®ion[3],®ion[3],timeout.c_str(),arch, kernel); + + do_cmd(dw, kernel, LEN); + return 0; +} + +static int check_btf_file(char *btf) +{ + struct stat fstat; + int ret = 0; + + ret = stat(btf, &fstat); + if (ret) + return -1; + if (fstat.st_size < 10*1024) + return -1; + + return 0; +} + +int offset_init(void) +{ + int ret = 0; + char btf[LEN] = {0}; + char ver[LEN] = {0}; + const char *cmd; + + cmd = string("uname -r").c_str(); + do_cmd(cmd, ver, LEN); + if(getenv("SYSAK_WORK_PATH") != NULL) + sprintf(btf,"%s/tools/%s/vmlinux-%s", getenv("SYSAK_WORK_PATH"), ver, ver); + else + sprintf(btf,"/boot/vmlinux-%s", ver); + + if (check_btf_file(btf)) { + download_btf(); + }; + + if (check_btf_file(btf)) { + printf("btf file:%s not found \n", btf); + return -1; + } + ret = sym_init(btf); + if (!!ret) { + printf("get sym init error\n"); + return -1; + } + + get_offset("page", "mapping"); + get_offset("address_space", "host"); + get_offset("address_space", "nrpages"); + get_offset("inode", "i_ino"); + get_offset("inode", "i_size"); + get_offset("inode", "i_sb"); + get_offset("inode", "i_dentry"); + get_offset("dentry", "d_alias"); + get_offset("dentry", "d_parent"); + get_offset("dentry", "d_hash"); + get_offset("dentry", "d_name"); + get_offset("dentry", "d_name"); + get_offset("super_block", "s_mounts"); + get_offset("mount", "mnt_instance"); + get_offset("mount", "mnt_parent"); + get_offset("mount", "mnt_mountpoint"); + get_offset("mount", "mnt_mountpoint"); + + return 0; +} + diff --git a/source/tools/monitor/unity/collector/podMan/podsAll.lua b/source/tools/monitor/unity/collector/podMan/podsAll.lua index 9e81eba0..16e0919a 100644 --- a/source/tools/monitor/unity/collector/podMan/podsAll.lua +++ b/source/tools/monitor/unity/collector/podMan/podsAll.lua @@ -102,6 +102,40 @@ local function setupCons(res) return cons end +function CpodsAll:getAllcons(procfs) + local mnt = procfs + local runtime = getRuntime(mnt) + local cli = ChttpCli.new() + local cons = {} + local c = 0 + local content = cli:get("http://127.0.0.1:10255/pods") + if #content.body == 0 then return cons end + local obj = cli:jdecode(content.body) + + for _, pod in ipairs(obj.items) do + local metadata = pod.metadata + local lpod = {name = metadata.name, + namespace = metadata.namespace, + uid = pystring:replace(metadata.uid, "-", "_"), + qos = pystring:lower(pod.status.qosClass), + } + local containerStatuses = pod.status.containerStatuses + for _, con in ipairs(containerStatuses) do + local cell = { + pod = lpod, + name = con.name, + id = spiltConId(con.containerID) + } + cell.path = joinPath(cell, runtime) + if unistd.access(mnt .. "/sys/fs/cgroup/memory/" .. cell.path) == 0 then + c = c + 1 + cons[c] = cell + end + end + end + return cons +end + local function setupPlugins(res, proto, pffi, mnt, ino) local c = 0 local cons = setupCons(res) diff --git a/source/tools/monitor/unity/collector/podmem.lua b/source/tools/monitor/unity/collector/podmem.lua new file mode 100644 index 00000000..dda3d61c --- /dev/null +++ b/source/tools/monitor/unity/collector/podmem.lua @@ -0,0 +1,111 @@ +--- +--- Generated by EmmyLua(https://github.com/EmmyLua) +--- Created by liuxinwnei. +--- DateTime: 2023/05/29 17:00 PM +--- + +require("common.class") +local fcntl = require("posix.fcntl") +local unistd = require("posix.unistd") +local dirent = require("posix.dirent") +local stdlib = require("posix.stdlib") +local stat = require("posix.sys.stat") +local CkvProc = require("collector.kvProc") +local CvProc = require("collector.vproc") +local pystring = require("common.pystring") +local dockerinfo = require("common.dockerinfo") +local json = require("cjson") +local CPodMem = class("podmem", CkvProc) +local ChttpCli = require("httplib.httpCli") +local podman = require("collector.podMan.podsAll") + +function CPodMem:_init_(proto, pffi, mnt, pFile) + CkvProc._init_(self, proto, pffi, mnt, pFile , "podmem") + self._ffi = require("collector.native.plugincffi") + self.cffi = self._ffi.load("podmem") + self.root_fs = mnt + self.proc_fs = mnt .. "/proc/" + self.allcons = {} + self.inodes = {} + self.podmemres = {} + self.blacklist = {["arms-prom"] = 1, ["kube-system"] = 1, ["kube-public"] = 1, ["kube-node-lease"] = 1} + -- self.blacklist= {} + self.cffi.monitor_init(self.root_fs) +end + +-- function CPodMem:_del_() +-- self.cffi.monitor_exit() +-- end + +function CPodMem:get_inode(file) + local f=stat.lstat(file) + if f ~= nil then + return f["st_ino"] + else + return -1 + end +end + + +function CPodMem:get_allcons() + local cri_cons = podman:getAllcons(self.root_fs) + for _,v in pairs(cri_cons) do + if not self.blacklist[v['pod']['namespace']] then + local path = self.root_fs .. "/sys/fs/cgroup/memory/" .. v['path'] + local inode = self:get_inode(path) + self.allcons[v['name']..v['pod']['name']] = {["pod"]=v['pod']['name'], ["ns"]=v['pod']['namespace'], ["path"]=path, ["inode"] = inode} + self.inodes[inode] = v['name']..v['pod']['name'] + end + end +end + +function CPodMem:proc(elapsed, lines) + CvProc.proc(self) + self.allcons = {} + self.inodes = {} + self.podmemres = {} + self:get_allcons() + -- for k,v in pairs(self.inodes) do print(k,v) end + -- for k,v in pairs(self.allcons) do for k1,v1 in pairs(v) do print(k,k1,v1) end end + local fs = io.open("/tmp/.memcg.txt", "w") + for k,v in pairs(self.allcons) do + fs:write(v['path']) + fs:write("\n") + end + fs:close() + + local resptr = self.cffi.scanall() + if not resptr then return end + + local res = self._ffi.string(resptr) + + local reslines = pystring:splitlines(res) + for _,line in pairs(reslines) do + local cinode, cache, size, filen = line:match("cinode=(%d+) cached=(%d+) size=(%d+) file=(%S+)") + if self.inodes[tonumber(cinode)] ~= nil then + if filen:find("overlayfs/snapshots/%d+/fs") ~= nil then + filen = pystring:split(pystring:split(filen,"overlayfs/snapshots/")[2],"/fs/")[2] + filen = "/" .. filen + end + if filen:find("diff") ~= nil then filen = pystring:split(filen,"diff")[2] end + local cname = self.inodes[tonumber(cinode)] + if not self.podmemres[cname] then self.podmemres[cname]= {} end + self.podmemres[cname][filen] = {["pod"]=self.allcons[cname]['pod'], ["ns"]=self.allcons[cname]['ns'], ["size"]=size, ["cache"]=cache} + end + end + self._ffi.C.free(resptr) + + for k,v in pairs(self.podmemres) do + for k1,v1 in pairs(v) do + -- for k2,v2 in pairs(v1) do print(k,k1,k2,v2) end + local cell = {{name="podmem_size", value=v1['size']}} + local label = {{name="podname",index=v1['pod'],}, {name="podns",index = v1['ns'],},{name="file",index = k1,},} + self:appendLine(self:_packProto("podmem", label, cell)) + cell = {{name="podmem_cache", value=v1['cache']}} + label = {{name="podname",index=v1['pod'],}, {name="podns",index = v1['ns'],},{name="file",index = k1,},} + self:appendLine(self:_packProto("podmem", label, cell)) + end + end + self:push(lines) +end +return CPodMem -- Gitee From 1e88b01dff23de079d1c5d7d756a07862cb7bedf Mon Sep 17 00:00:00 2001 From: zhilan Date: Wed, 7 Jun 2023 03:37:39 +0000 Subject: [PATCH 2/3] podmem to unity: add container name to index --- source/tools/monitor/unity/collector/podmem.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/tools/monitor/unity/collector/podmem.lua b/source/tools/monitor/unity/collector/podmem.lua index dda3d61c..8b6cedad 100644 --- a/source/tools/monitor/unity/collector/podmem.lua +++ b/source/tools/monitor/unity/collector/podmem.lua @@ -53,7 +53,7 @@ function CPodMem:get_allcons() if not self.blacklist[v['pod']['namespace']] then local path = self.root_fs .. "/sys/fs/cgroup/memory/" .. v['path'] local inode = self:get_inode(path) - self.allcons[v['name']..v['pod']['name']] = {["pod"]=v['pod']['name'], ["ns"]=v['pod']['namespace'], ["path"]=path, ["inode"] = inode} + self.allcons[v['name']..v['pod']['name']] = {["pod"]=v['pod']['name'], ["ns"]=v['pod']['namespace'], ["path"]=path, ["inode"] = inode, ["cname"]=v['name']} self.inodes[inode] = v['name']..v['pod']['name'] end end @@ -90,7 +90,7 @@ function CPodMem:proc(elapsed, lines) if filen:find("diff") ~= nil then filen = pystring:split(filen,"diff")[2] end local cname = self.inodes[tonumber(cinode)] if not self.podmemres[cname] then self.podmemres[cname]= {} end - self.podmemres[cname][filen] = {["pod"]=self.allcons[cname]['pod'], ["ns"]=self.allcons[cname]['ns'], ["size"]=size, ["cache"]=cache} + self.podmemres[cname][filen] = {["pod"]=self.allcons[cname]['pod'], ["ns"]=self.allcons[cname]['ns'], ["size"]=size, ["cache"]=cache, ["cname"]=self.allcons[cname]['cname']} end end self._ffi.C.free(resptr) @@ -99,10 +99,10 @@ function CPodMem:proc(elapsed, lines) for k1,v1 in pairs(v) do -- for k2,v2 in pairs(v1) do print(k,k1,k2,v2) end local cell = {{name="podmem_size", value=v1['size']}} - local label = {{name="podname",index=v1['pod'],}, {name="podns",index = v1['ns'],},{name="file",index = k1,},} + local label = {{name="podname",index=v1['pod'],}, {name="podns",index = v1['ns'],},{name="file",index = k1,},{name="container", index=v1['cname']},} self:appendLine(self:_packProto("podmem", label, cell)) cell = {{name="podmem_cache", value=v1['cache']}} - label = {{name="podname",index=v1['pod'],}, {name="podns",index = v1['ns'],},{name="file",index = k1,},} + label = {{name="podname",index=v1['pod'],}, {name="podns",index = v1['ns'],},{name="file",index = k1,},{name="container", index=v1['cname']},} self:appendLine(self:_packProto("podmem", label, cell)) end end -- Gitee From 1bd38ad0cb5312cdad7a057bc9282f051ba5fedb Mon Sep 17 00:00:00 2001 From: zhilan Date: Wed, 7 Jun 2023 13:19:36 +0800 Subject: [PATCH 3/3] podmem to unity: fix bugs in path of downlaod btf --- .../tools/monitor/unity/collector/plugin/podmem/offset.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/tools/monitor/unity/collector/plugin/podmem/offset.cpp b/source/tools/monitor/unity/collector/plugin/podmem/offset.cpp index fab42813..882aae60 100644 --- a/source/tools/monitor/unity/collector/plugin/podmem/offset.cpp +++ b/source/tools/monitor/unity/collector/plugin/podmem/offset.cpp @@ -151,10 +151,11 @@ static int download_btf(void) if(getenv("SYSAK_WORK_PATH") != NULL) { sysak_path = getenv("SYSAK_WORK_PATH") ; - sysak_path += "/tools"; + sysak_path += "/tools/"; + sysak_path += kernel; } - snprintf(dw, LEN + LEN + LEN, "wget -T 5 -t 2 -q -O %s/%s/vmlinux-%s https://sysom-cn-%s.oss-cn-%s%s.aliyuncs.com/home/hive/btf/%s/vmlinux-%s",sysak_path.c_str(), kernel, kernel, ®ion[3],®ion[3],timeout.c_str(),arch, kernel); + snprintf(dw, LEN + LEN + LEN, "wget -T 5 -t 2 -q -O %s/vmlinux-%s https://sysom-cn-%s.oss-cn-%s%s.aliyuncs.com/home/hive/btf/%s/vmlinux-%s",sysak_path.c_str(), kernel, ®ion[3],®ion[3],timeout.c_str(),arch, kernel); do_cmd(dw, kernel, LEN); return 0; -- Gitee