当前位置: 首页 > news >正文

【负载均衡在线OJ项目日记】编译与日志功能开发

目录

日志功能开发

常见的日志等级

日志功能代码

编译功能开发

创建子进程和程序替换

重定向

编译功能代码


日志功能开发

日志在软件开发和运维中起着至关重要的作用,目前我们不谈运维只谈软件开发;日志最大的作用就是用于故障排查和调试;

当系统出现问题时,日志记录可以帮助开发人员追踪问题的根源。通过查看日志文件,开发人员可以了解系统在发生故障之前的行为,识别错误发生的时间、地点和原因,并快速定位到错误的代码或功能模块。

因此我们要为目前这个项目编写一个简单的日志模块,这个模块可能被项目中的任何一个部分使用,我们将其放在公共模块的一个文件中。

常见的日志等级

  1. DEBUG(调试): 用于记录程序的详细运行信息,通常用于开发和调试阶段,帮助开发人员定位问题和追踪程序流程。

  2. INFO(信息): 用于记录程序正常运行时的重要信息,例如启动信息、关键操作记录等,可用于了解系统的基本运行情况。

  3. WARNING(警告): 用于记录一些潜在的问题或异常情况,虽然不会导致系统崩溃或功能失效,但需要开发人员注意和处理,以避免可能的错误。

  4. ERROR(错误): 用于记录错误事件,表示程序发生了一些可恢复的错误,但并未导致程序完全失败,通常需要开发人员及时处理以保证系统的正常运行。

  5. FATAL(致命错误): 用于记录严重错误事件,表示程序发生了无法恢复的错误,导致程序崩溃或功能失效,需要立即进行修复和处理,以保证系统的稳定性和可靠性。

基于这个项目,目前我们实现的时文件版本;因此我们需要打印出日志等级、文件名称、报错行、时间戳。

日志功能代码

Log.hpp

#pragma once
#include <iostream>
#include <string>
#include "util.hpp"
using namespace std;
namespace ns_log
{using namespace ns_util;// 日志等级enum{INFO,    // 就是整数0DEBUG,   // 1WARNING, // 2ERROR,   // 3FATAL    // 4};// 参数// 日志等级// 文件名// 行数// 标准输出流返回给用户inline ostream &Log(const string &level, const string &file_name, const int line){// 添加日志等级string message = "[";message += level;message += "]";// 添加报错文件名称message += "[";message += file_name;message += "]";// 添加报错行message += "[";message += to_string(line);message += "]";// 日志时间戳message += "[";message += TimeUtil::GetTimeStamp();message += "]";// cout 本质内部是包含缓冲区的//cout << message; // 不要endl刷新// 此时message 就在缓冲区中return cout;}
// LOG(INFO)<<"message"<<endl;
// 开放日志
#define LOG(level) Log(#level, __FILE__, __LINE__)
}

最后我们宏定义这个函数调用,参数#level 用于将参数 level 转换成一个字符串,参数__FILE____LINE__ 是预定义的宏,在编译时由编译器自动替换为当前源文件的文件名和代码行号。

时间信息也是一个公用的信息我们会在另一个文件中实现。


编译功能开发

首先我们要明白这个模块只负责进行代码编译,那么意味着我们目前默认是能够接收远端提交的代码文件,并且这个文件对于我们编译模块来说是一个临时文件,如果编译成功后也会形成一个临时的可执行文件,因此在这个模块中我们还需要一个临时文件的文件夹。但是对于这个模块中目前的进程是用来接收代码文件的,对于提交的代码文件我们如何处理呢?

创建子进程和程序替换

因为编译对于操作系统来也是执行了一个程序,只不过这个程序很小,过程快而已;因此我们可以创建一个子进程,让子进程进行程序替换,替换我们的编译指令程序。

重定向

编译代码就两种结果:编译成功或者编译失败;编译成功就是我们想要的结果,可以通过判断是否生成可执行文件判断这个结果;对于编译失败,编译失败的信息会向我们的显示器打印,但是我们是要将信息返回给使用者的;因此我们就需要将错误信息重定向到一个错误文件中。

编译功能代码

compiler.hpp

// 主要进行编译服务
#pragma once// 编译服务器
#include <iostream>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include"../comm/util.hpp"
#include"../comm/Log.hpp"
using namespace std;// 只负责进行代码编译// 默认代码能够接收// 远端提交代码// 一定要能够形成临时文件// 第一种编译通过
// 第二种编译出错
// 本质是像stderr错误中打印---->需要形成临时文件 ,帮助我们保存编译出错的结果的// 不能让这个进程编译
// 核心思路:创建子进程(fork())---->子进程完成编译代码 编译错误向stderr中打印(默认是向显示屏打印) 需要重定向到stderr中
// 父进程继续执行namespace ns_compiler
{//引入路径拼接功能using namespace ns_util;using namespace ns_log;class Compiler{public:Compiler(){}~Compiler(){}//编译//返回值:编译成功:true 编译失败:false//参数:编译代码的文件名//1234//./temp/1234.cpp//./tmep/1234.exe//./temp/1234.stderr//编译错误临时文件static bool Compile(const std::string &file_name)//temp文件夹保存临时文件{pid_t pid = fork();if(pid<0){//创建子进程失败LOG(ERROR)<<"内部错误,创建子进程失败"<<"\n";return false;}else if(pid==0){//需要一个错误文件int _stderr = open(PathUtil::Stderr(file_name).c_str(),O_CREAT|O_WRONLY,644);//if(_stderr<0){//打开文件失败LOG(WARNING)<<"没有成功形成stderr文件"<<"\n";exit(1);}//编译错误时才会向文件中写入//重定向dup2(_stderr,2);//子进程:调用编译器完成对代码的编译工作//程序替换//不需要冗余的路径//g++ -o target src -std=c++11//程序替换并不影响文件描述符表//我想执行谁,怎么执行execlp("g++","g++","-o",PathUtil::Exe(file_name).c_str(),PathUtil::Src(file_name).c_str(),"-std=c++11",nullptr/*不要忘记*/);LOG(ERROR) <<"启动编译器g++失败,可能是参数错误"<<"\n";exit(2);}else {//父进程waitpid(pid,nullptr,0);//编译是否成功---->是否形成可执行程序if(FileUtil::IsFileExists(PathUtil::Exe(file_name))){LOG(INFO)<<PathUtil::Src(file_name)<<" 编译成功!"<<"\n";return true;}}LOG(ERROR)<<"编译失败,没有形成可执行程序"<<"\n";return false;}};
}

until.hpp

#pragma once
#include <iostream>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
using namespace std;
namespace ns_util
{const std::string temp_path = "./temp/";// 路径class PathUtil{public:static std::string AddSuffix(const std::string &file_name, const std::string suffix){std::string path_name = temp_path;path_name += file_name;path_name += suffix;return path_name;}// 构建源文件路径+后缀的完整文件名// 1234->./temp/1234.cppstatic std::string Src(const std::string &file_name){return AddSuffix(file_name, ".cpp");}// 构建可执行程序的完整路径+后缀static std::string Exe(const std::string &file_name){return AddSuffix(file_name, ".exe");}// 构建该程序对应的标准错误完整的的路径+后缀名static std::string Stderr(const std::string &file_name){return AddSuffix(file_name, ".stderr");}};class FileUtil{public:static bool IsFileExists(const std::string path_name){// 通过判断获取文件属性判断文件是否存在struct stat st;if (stat(path_name.c_str(), &st) == 0){// 获取文件属性成功代表文件存在return true;}return false;}};class TimeUtil{public:static string GetTimeStamp(){struct timeval _time;gettimeofday(&_time, nullptr);return to_string(_time.tv_sec);}};
}

今天对项目编译和日志功能开发的分享到这就结束了,希望大家读完后有很大的收获,也可以在评论区点评文章中的内容和分享自己的看法;个人主页还有很多精彩的内容。您三连的支持就是我前进的动力,感谢大家的支持!!! 

相关文章:

【负载均衡在线OJ项目日记】编译与日志功能开发

目录 日志功能开发 常见的日志等级 日志功能代码 编译功能开发 创建子进程和程序替换 重定向 编译功能代码 日志功能开发 日志在软件开发和运维中起着至关重要的作用&#xff0c;目前我们不谈运维只谈软件开发&#xff1b;日志最大的作用就是用于故障排查和调试&#x…...

yaml配置文件的在深度学习中的简单应用

1 .创作灵感 小伙伴们再阅读深度学习模型的代码的时候&#xff0c;经常会遇到yaml格式的配置文件。用这个配置文件是因为我们在训练模型的时候会涉及很多的参数&#xff0c;如果这些参数东一个&#xff0c;西一个&#xff0c;我们调起来的时候就会很不方便&#xff0c;所以用y…...

spring boot 核心配置文件是什么?

Spring Boot 的核心配置文件主要是 application.properties 或 application.yml&#xff08;也称为 YAML 格式&#xff09;。这两个文件通常位于项目的 src/main/resources 目录下&#xff0c;用于配置 Spring Boot 应用程序的各种属性和设置。 application.properties&#xf…...

Python的奇妙之旅——回顾其历史

我们这个神奇的宇宙里&#xff0c;有一个名叫Python的小家伙&#xff0c;它不仅聪明&#xff0c;而且充满活力。它一路走来&#xff0c;从一个小小的编程语言成长为如今全球最受欢迎的编程语言之一。今天&#xff0c;我们就来回顾一下Python的历史&#xff0c;看看它如何从一个…...

Flink面试整理-Flink的性能优化策略

Apache Flink 的性能优化是一个多方面的任务,涉及硬件资源、算法选择、配置调整等多个层面。以下是一些常见的 Flink 性能优化策略: 1. 资源分配和管理 合理配置 TaskManager 和 JobManager:根据作业的需求和可用资源,合理分配内存和 CPU 给 TaskManager 和 JobManager。适…...

SpringBoot与SpringMVC的区别

SpringBoot与SpringMVC的区别是什么&#xff1f; SpringBoot和SpringMVC是Java开发中常用的两个框架&#xff0c;它们都是由Spring框架所提供的&#xff0c;但在功能和使用方式上有着一些区别。本文将分别介绍SpringBoot和SpringMVC的特点和区别。 一、SpringBoot的特点&#…...

漏洞挖掘之某厂商OAuth2.0认证缺陷

0x00 前言 文章中的项目地址统一修改为: a.test.com 保护厂商也保护自己 0x01 OAuth2.0 经常出现的地方 1&#xff1a;网站登录处 2&#xff1a;社交帐号绑定处 0x02 某厂商绑定微博请求包 0x02.1 请求包1&#xff1a; Request: GET https://www.a.test.com/users/auth/weibo?…...

电脑屏幕监控软件都有哪些 | 五大好用屏幕监控软件盘点

电脑屏幕监控软件在企业管理、家庭教育等方面发挥着越来越重要的作用。 这些软件通过实时监控电脑屏幕活动&#xff0c;为用户提供了强大的管理和监控功能。 本文将为您盘点五大好用的电脑屏幕监控软件&#xff0c;帮助您更好地了解并选择适合自己的软件。 电脑屏幕监控软件都…...

数据结构-线性表-链表-2.3-2

在带头节点的单链表L中&#xff0c;删除所有值为x的结点&#xff0c;并释放其空间&#xff0c;假设值为x的结点不唯一&#xff0c; 是编写算法实现上述操作。 双指针&#xff0c;用p从头至尾扫描单链表&#xff0c;pre指向*p结点的前驱&#xff0c;若p所指结点的值为x&#x…...

【自动化测试】使用MeterSphere进行接口测试

一、接口介绍二、接口测试的过程三、接口自动化测试执行自动化流程 四、接口之间的协议HTTP协议 五、 接口测试用例设计接口文档 六、使用MeterSphere创建接口测试创建接口定义设计接口测试用例 一、接口介绍 自动化测试按对象分为&#xff1a;单元测试、接口测试、UI测试等。…...

C语言 main( ) 函数的指针数组形参是怎么回事?

一、问题 在使⽤⼀些开发⼯具⽣成C语⾔⽂件时&#xff0c;主函数 mian( ) 中会有参数&#xff0c;这个参数到底是怎么回事⼉呢&#xff1f; 二、解答 mian( ) 称为主函数&#xff0c;是所有程序运⾏的⼊口。 mian( ) 函数是由系统调⽤的&#xff0c;当处于操作命令状态下&…...

汽车 - 什么是车轮抱死

车轮抱死分为两种情况&#xff0c;一种是车辆故障层面&#xff0c;另一种是驾驶过程中的物理现象。我们先来说最通俗的刹车车轮抱死吧。 刹车制动车轮抱死 车轮停止轴向转动就是抱死&#xff0c;有速度的情况下抱死车轮&#xff0c;如果车辆的惯性动能大于轮胎抓地力&#xff0…...

环保设备统一管理系统

在环保意识日益增强的今天&#xff0c;企业如何有效管理环保设备&#xff0c;确保其正常运行&#xff0c;减少环境污染&#xff0c;成为了一个重要议题。HiWoo Cloud平台以其独特的环保设备统一管理系统&#xff0c;为企业提供了一套完整的解决方案&#xff0c;帮助企业实现绿色…...

python 11Pandas数据可视化实验

实验目的&#xff1a; 学会使用Pandas操作数据集&#xff0c;并进行可视化。 数据集描述&#xff1a; 该数据集是CNKI中与“中药毒理反应”相关的文献信息&#xff0c;包含文章题目、作者、来源&#xff08;出版社&#xff09;、摘要、发表时间等信息。 实验要求&#xff1…...

【JUC】并发编程 AQS,ReentryLock,CyclicBarrier,CountDownLatch 原理总结

AQS AQS是什么&#xff1f;重写AQS就能实现锁的效果&#xff1f; AQS是一个抽象类&#xff0c;是一个并发包的基础组件&#xff0c;用来实现各种锁&#xff0c;同步组件的工具&#xff08;通过volatile cas进行实现&#xff09;。它包含了共享成员变量state、等待队列、条件…...

移动端底层事件(如左滑返回事件)在同一个路由下不同页面需要不同的处理要怎样才能做到统一处理?

目录 一、问题 二、解决方法 三、总结 tiips:如嫌繁琐&#xff0c;直接移步总结即可&#xff01; 一、问题 1.测试提了个bug:进入了一个模块A里面的子页面 a1,左滑后按照用户预期应该是返回到模块A,结果回到了app首页。 二、解决方法 1.一开始&#xff1a;啊&#xff0c;…...

hive中开窗函数row_number的使用

row_number()函数介绍 row_number()开窗函数的一种&#xff0c;和over()函数结合一起使用&#xff0c;可以实现对数据的分组和排序。 使用示例 现在有一张表&#xff0c;数据如下 ----------------------- | Year | Region | Sales | ----------------------- | 2022 | E…...

华为数据之道第三部分导读

目录 导读 第三部分 第7章 打造“数字孪生”的数据全量感知能力 “全量、无接触”的数据感知能力框架 数据感知能力的需求起源&#xff1a;数字孪生 数据感知能力架构 基于物理世界的“硬感知”能力 “硬感知”能力的分类 “硬感知”能力在华为的实践 基于数字世界的…...

【Qt】常用控件(一)

文章目录 一、核心属性1、enabled代码示例: 通过按钮2 切换按钮1 的禁用状态 2、geometry代码示例: 控制按钮的位置代码示例&#xff1a;window frame 的影响代码示例: 感受 geometry 和 frameGeometry 的区别 3、windowTitle4、windowIcon代码示例: 通过 qrc 管理图片作为图标…...

Python基础之流程控制语句

在Python中流程控制语句包括条件控制语句、循环语句、以及控制流程循环语句等,下面我们就来详细介绍一下这些语句的使用。 条件语句 首先我们来看条件语句,条件语句是需要根据不同的判断条件来执行不同的代码操作,如下所示。 if 条件1:执行语句块1 elif 条件2:执行语句块…...

变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析

一、变量声明设计&#xff1a;let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性&#xff0c;这种设计体现了语言的核心哲学。以下是深度解析&#xff1a; 1.1 设计理念剖析 安全优先原则&#xff1a;默认不可变强制开发者明确声明意图 let x 5; …...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...