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

工程化与框架系列(30)--前端日志系统实现

前端日志系统实现 📝

引言

前端日志系统是应用监控和问题诊断的重要工具。本文将深入探讨前端日志系统的设计与实现,包括日志收集、处理、存储和分析等方面,帮助开发者构建完整的前端日志解决方案。

日志系统概述

前端日志系统主要包括以下方面:

  • 日志收集:用户行为、性能指标、错误信息等
  • 日志处理:过滤、格式化、压缩等
  • 日志存储:本地存储、远程上传等
  • 日志分析:统计分析、可视化展示等
  • 实时监控:告警、通知等

日志系统实现

日志管理器

// 日志管理器类
class LogManager {private static instance: LogManager;private config: LogConfig;private logQueue: LogEntry[];private timer: number | null;private storage: Storage;private constructor() {this.config = {appId: '',appVersion: '',maxQueueSize: 100,flushInterval: 5000,logLevel: LogLevel.INFO,uploadUrl: '',enableConsole: true,enableStorage: true,maxStorageSize: 5 * 1024 * 1024 // 5MB};this.logQueue = [];this.timer = null;this.storage = new Storage('logs', this.config.maxStorageSize);this.initialize();}// 获取单例实例static getInstance(): LogManager {if (!LogManager.instance) {LogManager.instance = new LogManager();}return LogManager.instance;}// 初始化日志管理器initialize(config?: Partial<LogConfig>): void {if (config) {this.config = { ...this.config, ...config };}// 加载本地存储的日志if (this.config.enableStorage) {this.loadStoredLogs();}// 启动定时上传this.startAutoUpload();// 注册页面卸载事件window.addEventListener('beforeunload', () => {this.flush();});}// 记录日志log(level: LogLevel,message: string,data?: any,tags?: string[]): void {// 检查日志级别if (level < this.config.logLevel) {return;}const logEntry = this.createLogEntry(level, message, data, tags);// 输出到控制台if (this.config.enableConsole) {this.printToConsole(logEntry);}// 添加到队列this.addToQueue(logEntry);}// 创建日志条目private createLogEntry(level: LogLevel,message: string,data?: any,tags?: string[]): LogEntry {return {appId: this.config.appId,appVersion: this.config.appVersion,timestamp: Date.now(),level,message,data,tags,url: window.location.href,userAgent: navigator.userAgent};}// 添加到日志队列private addToQueue(entry: LogEntry): void {this.logQueue.push(entry);// 保存到本地存储if (this.config.enableStorage) {this.storage.append(entry);}// 队列超出限制时立即上传if (this.logQueue.length >= this.config.maxQueueSize) {this.flush();}}// 输出到控制台private printToConsole(entry: LogEntry): void {const { level, message, data } = entry;const timestamp = new Date(entry.timestamp).toISOString();const style = this.getConsoleStyle(level);const prefix = `%c[${timestamp}][${LogLevel[level]}]`;if (data) {console.log(prefix, style, message, data);} else {console.log(prefix, style, message);}}// 获取控制台样式private getConsoleStyle(level: LogLevel): string {switch (level) {case LogLevel.ERROR:return 'color: #ff4444; font-weight: bold';case LogLevel.WARN:return 'color: #ffbb33; font-weight: bold';case LogLevel.INFO:return 'color: #33b5e5';case LogLevel.DEBUG:return 'color: #999999';default:return '';}}// 启动自动上传private startAutoUpload(): void {if (this.timer !== null) {return;}this.timer = window.setInterval(() => {this.flush();}, this.config.flushInterval);}// 停止自动上传private stopAutoUpload(): void {if (this.timer === null) {return;}window.clearInterval(this.timer);this.timer = null;}// 立即上传日志async flush(): Promise<void> {if (this.logQueue.length === 0) {return;}const logs = [...this.logQueue];this.logQueue = [];try {await this.uploadLogs(logs);// 清理已上传的本地存储日志if (this.config.enableStorage) {this.storage.clear();}} catch (error) {console.error('Failed to upload logs:', error);// 重新加入队列this.logQueue.push(...logs);}}// 上传日志到服务器private async uploadLogs(logs: LogEntry[]): Promise<void> {const response = await fetch(this.config.uploadUrl, {method: 'POST',headers: {'Content-Type': 'application/json'},body: JSON.stringify(logs)});if (!response.ok) {throw new Error('Failed to upload logs');}}// 加载存储的日志private loadStoredLogs(): void {const logs = this.storage.getAll();this.logQueue.push(...logs);}
}// 日志级别枚举
enum LogLevel {DEBUG,INFO,WARN,ERROR
}// 日志配置接口
interface LogConfig {appId: string;appVersion: string;maxQueueSize: number;flushInterval: number;logLevel: LogLevel;uploadUrl: string;enableConsole: boolean;enableStorage: boolean;maxStorageSize: number;
}// 日志条目接口
interface LogEntry {appId: string;appVersion: string;timestamp: number;level: LogLevel;message: string;data?: any;tags?: string[];url: string;userAgent: string;
}// 本地存储类
class Storage {private key: string;private maxSize: number;constructor(key: string, maxSize: number) {this.key = key;this.maxSize = maxSize;}// 追加日志append(entry: LogEntry): void {const logs = this.getAll();logs.push(entry);// 检查存储大小while (this.getStorageSize(logs) > this.maxSize) {logs.shift();}localStorage.setItem(this.key, JSON.stringify(logs));}// 获取所有日志getAll(): LogEntry[] {const data = localStorage.getItem(this.key);return data ? JSON.parse(data) : [];}// 清空日志clear(): void {localStorage.removeItem(this.key);}// 获取存储大小private getStorageSize(data: any): number {return new Blob([JSON.stringify(data)]).size;}
}// 使用示例
const logger = LogManager.getInstance();// 初始化日志系统
logger.initialize({appId: 'my-app',appVersion: '1.0.0',uploadUrl: '/api/logs',logLevel: LogLevel.DEBUG
});// 记录不同级别的日志
logger.log(LogLevel.DEBUG, 'Debug message', { detail: 'debug info' });
logger.log(LogLevel.INFO, 'Info message', { user: 'John' });
logger.log(LogLevel.WARN, 'Warning message', null, ['auth']);
logger.log(LogLevel.ERROR, 'Error message', new Error('Something went wrong'));

性能监控

// 性能监控类
class PerformanceMonitor {private static instance: PerformanceMonitor;private logger: LogManager;private metrics: Map<string, number>;private constructor() {this.logger = LogManager.getInstance();this.metrics = new Map();this.initialize();}// 获取单例实例static getInstance(): PerformanceMonitor {if (!PerformanceMonitor.instance) {PerformanceMonitor.instance = new PerformanceMonitor();}return PerformanceMonitor.instance;}// 初始化监控器private initialize(): void {// 监听性能时间this.observePerformanceTimings();// 监听资源加载this.observeResourceTimings();// 监听长任务this.observeLongTasks();// 监听首次绘制this.observePaintTimings();}// 开始计时startTimer(name: string): void {this.metrics.set(name, performance.now());}// 结束计时endTimer(name: string): void {const startTime = this.metrics.get(name);if (startTime) {const duration = performance.now() - startTime;this.metrics.delete(name);this.logger.log(LogLevel.INFO, `Timer: ${name}`, {duration,type: 'timer'});}}// 记录自定义指标recordMetric(name: string,value: number,tags?: string[]): void {this.logger.log(LogLevel.INFO, `Metric: ${name}`, {value,type: 'metric'}, tags);}// 监听性能时间private observePerformanceTimings(): void {window.addEventListener('load', () => {// 等待所有资源加载完成setTimeout(() => {const timing = performance.timing;const metrics = {dns: timing.domainLookupEnd - timing.domainLookupStart,tcp: timing.connectEnd - timing.connectStart,request: timing.responseEnd - timing.requestStart,response: timing.responseEnd - timing.responseStart,dom: timing.domComplete - timing.domLoading,load: timing.loadEventEnd - timing.navigationStart};Object.entries(metrics).forEach(([name, value]) => {this.recordMetric(name, value, ['timing']);});}, 0);});}// 监听资源加载private observeResourceTimings(): void {const observer = new PerformanceObserver((list) => {list.getEntries().forEach(entry => {if (entry.entryType === 'resource') {const resource = entry as PerformanceResourceTiming;this.logger.log(LogLevel.INFO, `Resource: ${resource.name}`, {duration: resource.duration,transferSize: resource.transferSize,type: resource.initiatorType}, ['resource']);}});});observer.observe({ entryTypes: ['resource'] });}// 监听长任务private observeLongTasks(): void {const observer = new PerformanceObserver((list) => {list.getEntries().forEach(entry => {if (entry.entryType === 'longtask') {this.logger.log(LogLevel.WARN, 'Long task detected', {duration: entry.duration,type: 'longtask'});}});});observer.observe({ entryTypes: ['longtask'] });}// 监听首次绘制private observePaintTimings(): void {const observer = new PerformanceObserver((list) => {list.getEntries().forEach(entry => {if (entry.entryType === 'paint') {this.recordMetric(entry.name, entry.startTime, ['paint']);}});});observer.observe({ entryTypes: ['paint'] });}
}// 使用示例
const monitor = PerformanceMonitor.getInstance();// 记录自定义计时
monitor.startTimer('operation');
// ... 执行操作
monitor.endTimer('operation');// 记录自定义指标
monitor.recordMetric('memory_usage', performance.memory?.usedJSHeapSize || 0);

用户行为跟踪

// 用户行为跟踪类
class UserBehaviorTracker {private static instance: UserBehaviorTracker;private logger: LogManager;private sessionId: string;private pageStartTime: number;private constructor() {this.logger = LogManager.getInstance();this.sessionId = this.generateSessionId();this.pageStartTime = Date.now();this.initialize();}// 获取单例实例static getInstance(): UserBehaviorTracker {if (!UserBehaviorTracker.instance) {UserBehaviorTracker.instance = new UserBehaviorTracker();}return UserBehaviorTracker.instance;}// 初始化跟踪器private initialize(): void {// 记录页面访问this.trackPageView();// 监听用户交互this.trackUserInteractions();// 监听页面可见性this.trackPageVisibility();// 监听页面离开this.trackPageLeave();}// 生成会话IDprivate generateSessionId(): string {return `${Date.now()}-${Math.random().toString(36).slice(2)}`;}// 跟踪页面访问private trackPageView(): void {this.logger.log(LogLevel.INFO, 'Page view', {sessionId: this.sessionId,title: document.title,referrer: document.referrer,type: 'pageview'});}// 跟踪用户交互private trackUserInteractions(): void {// 点击事件document.addEventListener('click', (event) => {const target = event.target as HTMLElement;this.logger.log(LogLevel.INFO, 'User click', {sessionId: this.sessionId,element: target.tagName.toLowerCase(),id: target.id,class: target.className,text: target.textContent?.slice(0, 100),type: 'click'});});// 表单提交document.addEventListener('submit', (event) => {const form = event.target as HTMLFormElement;this.logger.log(LogLevel.INFO, 'Form submit', {sessionId: this.sessionId,formId: form.id,action: form.action,type: 'form'});});// 页面滚动let scrollTimeout: number;window.addEventListener('scroll', () => {clearTimeout(scrollTimeout);scrollTimeout = window.setTimeout(() => {const scrollDepth = Math.round((window.scrollY + window.innerHeight) /document.documentElement.scrollHeight * 100);this.logger.log(LogLevel.INFO, 'Page scroll', {sessionId: this.sessionId,depth: scrollDepth,type: 'scroll'});}, 500);});}// 跟踪页面可见性private trackPageVisibility(): void {document.addEventListener('visibilitychange', () => {const isVisible = document.visibilityState === 'visible';this.logger.log(LogLevel.INFO, 'Visibility change', {sessionId: this.sessionId,visible: isVisible,type: 'visibility'});if (!isVisible) {this.trackEngagementTime();}});}// 跟踪页面离开private trackPageLeave(): void {window.addEventListener('beforeunload', () => {this.trackEngagementTime();});}// 跟踪页面参与时间private trackEngagementTime(): void {const engagementTime = Date.now() - this.pageStartTime;this.logger.log(LogLevel.INFO, 'Engagement time', {sessionId: this.sessionId,duration: engagementTime,type: 'engagement'});}// 跟踪自定义事件trackEvent(category: string,action: string,label?: string,value?: number): void {this.logger.log(LogLevel.INFO, 'Custom event', {sessionId: this.sessionId,category,action,label,value,type: 'event'});}
}// 使用示例
const tracker = UserBehaviorTracker.getInstance();// 跟踪自定义事件
tracker.trackEvent('video', 'play', 'intro-video', 30);

最佳实践与建议

  1. 日志设计

    • 分级管理
    • 结构化数据
    • 采样控制
    • 安全考虑
  2. 性能优化

    • 批量处理
    • 压缩数据
    • 限制频率
    • 本地缓存
  3. 数据处理

    • 过滤敏感信息
    • 数据清洗
    • 聚合分析
    • 实时监控
  4. 存储策略

    • 分级存储
    • 定期清理
    • 容量控制
    • 备份恢复

总结

前端日志系统需要考虑以下方面:

  1. 日志收集与处理
  2. 性能监控与分析
  3. 用户行为跟踪
  4. 数据存储与管理
  5. 安全性与隐私

通过完善的日志系统,可以更好地监控和优化前端应用。

学习资源

  1. 日志系统设计指南
  2. 性能监控最佳实践
  3. 用户行为分析方法
  4. 数据可视化工具
  5. 监控平台搭建

如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

相关文章:

工程化与框架系列(30)--前端日志系统实现

前端日志系统实现 &#x1f4dd; 引言 前端日志系统是应用监控和问题诊断的重要工具。本文将深入探讨前端日志系统的设计与实现&#xff0c;包括日志收集、处理、存储和分析等方面&#xff0c;帮助开发者构建完整的前端日志解决方案。 日志系统概述 前端日志系统主要包括以…...

小爱音箱控制家里的NAS将影片在电视上播放-deepseek帮助下实现-慎入openmanux

天始规划 我给ai一个任务,不过我没那么多能力,听说AI代理很行,这个任务我打算交给它.就用现在火的,openmanu,功能简单,我来安装openmanus,并规划任务. 进入openmanu首页 https://github.com/wjcroom/OpenManus openusa推荐使用uv管理,打算安装在家里的nas虚拟机.uv和python环…...

jQuery EasyUI 扩展

jQuery EasyUI 扩展 引言 jQuery EasyUI 是一个基于 jQuery 的易于使用的界面扩展库,它简化了网页界面的开发过程。随着 Web 技术的不断发展,越来越多的开发者开始寻求对 jQuery EasyUI 的扩展,以满足不同场景下的需求。本文将详细介绍 jQuery EasyUI 的扩展方法、技巧以及…...

笔试刷题专题(一)

文章目录 最小花费爬楼梯&#xff08;动态规划&#xff09;题解代码 数组中两个字符串的最小距离&#xff08;贪心&#xff08;dp&#xff09;&#xff09;题解代码 点击消除题解代码 最小花费爬楼梯&#xff08;动态规划&#xff09; 题目链接 题解 1. 状态表示&#xff1…...

使用Docker部署前端应用到生产环境

前期准备 安装 Docker&#xff1a;确保你的开发机器和生产服务器都已经安装了 Docker。可以参考 Docker 官方安装指南 完成安装。准备前端项目&#xff1a;保证你的前端项目代码完整&#xff0c;并且能够在本地正常构建。 编写 Dockerfile Dockerfile 是用于构建 Docker 镜像…...

ES6(1) 简介与基础概念

1. ES6 简介 ES6&#xff08;ECMAScript 6&#xff09;是 JavaScript 的一个重要版本&#xff0c;它在 ES5 的基础上进行了扩展和优化。ES6 主要应用于现代 Web 开发&#xff0c;提高了 JavaScript 的编程效率和可读性。 2. ES6 与 JavaScript 的关系 JavaScript 是一种基于 E…...

redis数据库的介绍以及安装部署

一.redis数据库的介绍 借助nginx的upstream模块实现后端服务的负载均衡&#xff0c;如果后端服务采用的是会话的机制来识别客户端的身份&#xff0c;如果使用的调度算法是轮询算法的话&#xff0c;其中我们需要去做的就是实现后端服务的会话保持。 第一种换调度算法&#xff…...

MySQL数据库复杂的增删改查操作

在前面的文章中&#xff0c;我们主要学习了数据库的基础知识以及基本的增删改查的操作。接下去将以一个比较实际的公司数据库为例子&#xff0c;进行讲解一些较为复杂且现时需求的例子。 基础知识&#xff1a; 一文清晰梳理Mysql 数据库基础知识_字段变动如何梳理清楚-CSDN博…...

tomcat部署springboot+vue(不使用nginx)

1、首先将springboot项目打包为war包。 注意&#xff1a;将application.yml文件中添加以下信息&#xff1a; spring.jmx.enabledfalse 避免tomcat下部署多个项目&#xff0c;出现org.springframework.jmx.export.UnableToRegisterMBeanException:影响项目启动。 2、前段项目打…...

Flutter 从入门到进阶:构建跨平台应用的最佳实践

引言 Flutter 是 Google 推出的一款开源 UI 框架&#xff0c;能够帮助开发者使用 Dart 语言构建高性能、跨平台的移动、桌面和 Web 应用。它以 “一次编写&#xff0c;到处运行” 的特点吸引了众多开发者。Flutter 采用自绘 UI 渲染引擎&#xff08;Skia&#xff09;&#xff…...

ROS实践(三)机器人描述文件xacro(urdf扩展)

目录 一、定义 二、xacro 文件常见组成部分 1. 命名空间声明 2. 定义宏 3. 调用宏 4. 定义参数 5. 条件语句 6. 转换 xacro 文件为 urdf 7. gazebo标签 三、代码示例 1. gazebo标签使用&#xff08;仿真参数配置&#xff09; 2. 引用仿真配置并定义机器人模型&#x…...

微信小程序从右向左无限滚动组件封装(类似公告)

组件代码 wxml代码 <view class"container"><view class"text-wrapper"><!-- 这两个都不能删除,用来放无限滚动的,第一个滚完第二个接上,第二个滚完第一个又接上了 --><text class"scroll-text text1" style"left: …...

前端面试:axios 请求的底层依赖是什么?

在前端开发中&#xff0c;Axios 是一个流行的 JavaScript 库&#xff0c;用于发送 HTTP 请求。它简化了与 RESTful APIs 的交互&#xff0c;并提供了许多便利的方法与配置选项。要理解 Axios 的底层依赖&#xff0c;需要从以下几个方面进行分析&#xff1a; 1. Axios 基于 XML…...

【小白向】Ubuntu|VMware 新建虚拟机后打开 SSH 服务、在主机上安装vscode并连接、配置 git 的 ssh

常常有人问VMware-Tools装了也复制粘贴不了怎么办&#xff0c;这个东西影响因素太多了&#xff0c;具体解决办法你们可以参考一下&#xff1a;【经验】VMware&#xff5c;虚拟机只能使用鼠标无法使用键盘、装不了或装了VMware-Tools无法复制粘贴的可能解决办法_增强型键盘驱动程…...

UVC摄像头命令推流,推到rv1126里面去

ffmpeg命令查询UVC设备 .\ffmpeg.exe -list_devices true -f dshow -i dummy 上图是查询UVC设备的效果图&#xff0c;画红框的部分是UVC设备的设备名称"USB2.0 PC CAMERA"和设备号 "device_pnp_\\?\usb#vid_1908&pid_2310&mi_00#8&39abfe5&0&a…...

Node.js 与 MongoDB:高效的企业级应用开发

Node.js 与 MongoDB:高效的企业级应用开发 引言 随着互联网技术的飞速发展,企业级应用开发的需求日益增长。作为现代Web开发的重要工具,Node.js凭借其高性能、轻量级的特点,已经成为构建高效、可扩展后端服务的首选技术之一。而MongoDB作为一种流行的NoSQL数据库,以其灵…...

【大模型学习】第十九章 什么是迁移学习

目录 1. 迁移学习的起源背景 1.1 传统机器学习的问题 1.2 迁移学习的提出背景 2. 什么是迁移学习 2.1 迁移学习的定义 2.2 生活实例解释 3. 技术要点与原理 3.1 迁移学习方法分类 3.1.1 基于特征的迁移学习(Feature-based Transfer) 案例说明 代码示例 3.1.2 基于…...

sql-labs less-1-5wp

目录标题 less-1判断列数查找数据库和版本信息查找数据库中的表爆破users表的列爆破xx表xx列的数据 Less-2判断类型判断注释符和回显点爆破数据库和版本信息爆破security数据库的表爆破users表的列名爆破表中数据 Less-3判断类型判断注释符和回显点爆破爆破版本号和数据库爆数据…...

Unity开发的抖音小游戏接入抖音开放平台中的流量主(抖音小游戏接入广告)

前言:作者在进行小游戏审核版本的过程中,碰到了下列问题,所以对这个抖音小游戏接入广告研究了下。 还有就是作者的TTSDK版本号是6.2.6,使用的Unity版本是Unity2022.3.29f1,最好和作者的两个版本号保持一致,因为我发现TTSDK旧版的很多函数在新版中就已经无法正常使用了,必…...

在Simulink中将Excel数据导入可变负载模块的方法介绍

文章目录 数据准备与格式要求Excel数据格式MATLAB预处理数据导入方法使用From Spreadsheet模块(直接导入Excel)通过MATLAB工作区中转(From Workspace模块)使用1-D Lookup Table模块(非线性负载映射)Signal Builder模块(变载工况导入)可变负载模块配置注意事项与调试在S…...

Html5记忆翻牌游戏开发经验分享

H5记忆翻牌游戏开发经验分享 这里写目录标题 H5记忆翻牌游戏开发经验分享前言项目概述技术要点解析1. 页面布局&#xff08;HTML CSS&#xff09;响应式设计 2. 翻牌动画效果3. 游戏逻辑实现状态管理卡片配对检测 开发技巧总结1. 模块化设计2. 性能优化3. 用户体验 踩坑经验扩…...

Centos离线安装openssl-devel

文章目录 Centos离线安装openssl-devel1. openssl-devel是什么&#xff1f;2. openssl-devel下载地址3. openssl-devel安装4. 安装结果验证 Centos离线安装openssl-devel 1. openssl-devel是什么&#xff1f; openssl-devel 是 Linux 系统中与 OpenSSL 加密库相关的开发包&…...

Spring Boot项目中集成sa-token实现认证授权和OAuth 2.0第三方登录

OAuth 2.0第三方登录 OAuth 2.0 是一种授权协议&#xff0c;允许第三方应用在不暴露用户密码的情况下访问用户的资源。它通常用于第三方登录场景&#xff0c;例如使用GitHub、Google等社交平台进行登录。 在sa-token框架中&#xff0c;OAuth 2.0第三方登录可以通过集成sa-tok…...

【机器学习】迁移学习(Transfer Learning)

迁移学习&#xff08;Transfer Learning&#xff09;作为一种机器学习方法&#xff0c;主要通过将源域中学到的知识迁移到目标域&#xff0c;解决目标域中数据不足或标注困难的问题&#xff0c;尤其在无监督学习如聚类任务中具有显著优势。迁移学习的关键思想包括领域适应、知识…...

接入手机后,DeepSeek难“转正”

2025开年之后&#xff0c;手机圈掀起了一场诡异的AI军备竞赛——争相接入DeepSeek。随着时间的推移&#xff0c;这股年初的狂热已然降温。 当潮水退去之后&#xff0c;暴露出手机AI领域的残酷真相&#xff1a;市面上手机自带的AI能力&#xff0c;没能像DeepSeek一样&#xff0c…...

全链条自研可控|江波龙汽车存储“双轮驱动”体系亮相MemoryS 2025

3月12日&#xff0c;MemoryS 2025在深圳盛大开幕&#xff0c;汇聚了存储行业的顶尖专家、企业领袖以及技术先锋&#xff0c;共同探讨存储技术的未来发展方向及其在商业领域的创新应用。江波龙董事长、总经理蔡华波先生受邀出席&#xff0c;并发表了题为《存储商业综合创新》的主…...

宇树ROS1开源模型在ROS2中Gazebo中仿真

以GO1为例 1. CMakelists.txt更新语法 cmake_minimum_required(VERSION 3.8) project(go1_description) if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find…...

ubuntu 24 安装 python3.x 教程

目录 注意事项 一、安装不同 Python 版本 1. 安装依赖 2. 下载 Python 源码 3. 解压并编译安装 二、管理多个 Python 版本 1. 查看已安装的 Python 版本 2. 配置环境变量 3. 使用 update-alternatives​ 管理 Python 版本 三、使用虚拟环境为项目指定特定 Python 版本…...

Python数据类型进阶——详解

—— 小 峰 编 程 目录 1.整型 1.1 定义 1.2 独有功能 1.3 公共功能 1.4 转换 1.5 其他 1.5.1 长整型 1.5.2 地板除(除法&#xff09; 2. 布尔类型 2.1 定义 2.2 独有功能 2.3 公共功能 2.4 转换 2.5 其他 做条件自动转换 3.字符串类型 3.1 定义 3.2 独有功能…...

Flutter 按钮组件 TextButton 详解

目录 1. 引言 2. TextButton 的基本用法 3. 主要属性 4. 自定义按钮样式 4.1 修改文本颜色 4.2 添加背景色 4.3 修改按钮形状和边距 4.4 样式定制 5. 高级应用技巧 5.1 图标文本组合 5.2 主题统一配置 5.3 动态交互 6. 性能优化与注意事项 6.1 点击区域优化 6.…...

设置IDEA的内存

如何设置 IntelliJ IDEA 的内存以提升性能 一、引言 IntelliJ IDEA 是一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;广泛应用于 Java、Kotlin、Scala 等多种编程语言的开发。它以其丰富的功能、智能的代码提示和高效的项目管理能力深受开发者喜爱。然而&…...

python编写的一个打砖块小游戏

游戏介绍 打砖块是一款经典的街机游戏&#xff0c;玩家控制底部的挡板&#xff0c;使球反弹以击碎上方的砖块。当球击中砖块时&#xff0c;砖块消失&#xff0c;球反弹&#xff1b;若球碰到挡板&#xff0c;则改变方向继续运动&#xff1b;若球掉出屏幕底部&#xff0c;玩家失…...

MySQL异常SQL排查

0、明确数据库异常SQL执行时间段&#xff0c;正常情况下耗时&#xff0c;当前耗时&#xff0c;如何感知到数据库慢的&#xff0c;是哪种类型的SQL&#xff0c;近期有做过相关的变更吗 1、检查数据库服务器的io iostat //查看延迟、读、写流量 sar -d /var/log/sa/sar日期 …...

AI智能代码疫苗技术,赋能数字化应用内生安全自免疫

“DevSecOps市占率持续领先&#xff0c;IAST探针覆盖率十倍增长&#xff0c;代码疫苗技术已成功帮助上千家行业用户成功抵御‘Log4j2.x’等重大未知漏洞的利用攻击。”子芽在腾讯专访中透露。 这是2021年悬镜安全交出的一张成绩单。悬镜安全是DevSecOps敏捷安全先行者&#xf…...

ASP.NET Webform和ASP.NET MVC 后台开发 大概80%常用技术

本文涉及ASP.NET Webform和ASP.NET MVC 后台开发大概80%技术 2019年以前对标 深圳22K左右 广州18K左右 武汉16K左右 那么有人问了2019年以后的呢&#xff1f; 答&#xff1a;吉祥三宝。。。 So 想继续看下文的 得有自己的独立判断能力。 C#.NET高级笔试题 架构 优化 性能提…...

计算机视觉领域开源数据集资源整理

1. 目标检测数据集 1.1 COCO2017 数据集 COCO2017 是 2017 年发布的 COCO 数据集的一个版本&#xff0c;主要用于 COCO 在 2017 年后持有的物体检测任务、关键点检测任务和全景分割任务。 1.2 火焰和烟雾图像数据集 数据集链接&#xff1a;http://m6z.cn/6fzn0f 该数据集由…...

idea更新git代码报错No Git Roots

idea更新git代码报错&#xff1a; No Git Roots None of configured Git roots are under Git. The configured directory must have ".git directory in it.但是本地项目里是存在.git文件的&#xff0c;就是突然间不能更新代码了 然后尝试重新拉新项目代码提示: Git i…...

flutter EventBus 的使用介绍

一、EventBus 初识 EventBus 是一个只有20多行的代码库, 通常用它来做事件分发。 EventBus 遵从 publish/subscribe 模式,即发布/订阅模式;简化了模块之间通信,对于项目的解耦很实用; 组件地址: https://github.com/marcojakob/dart-event-bus 源码: class EventBus…...

Spring Boot 整合 Keycloak

1、概览 本文将带你了解如何设置 Keycloak 服务器&#xff0c;以及如何使用 Spring Security OAuth2.0 将Spring Boot应用连接到 Keycloak 服务器。 2、Keycloak 是什么&#xff1f; Keycloak是针对现代应用和服务的开源身份和访问管理解决方案。 Keycloak 提供了诸如单点登…...

4-001:MySQL 中的索引数量是否越多越好?为什么?

MySQL 中的索引并不是越多越好&#xff0c;索引数量要合理控制&#xff01; &#x1f4cc; 过多索引的影响 增加存储开销 每个索引都会占用额外的磁盘空间&#xff0c;索引多了&#xff0c;存储成本增加。 降低 INSERT、UPDATE、DELETE 性能 任何涉及数据修改的操作&#xff…...

C++蓝桥杯皮亚诺曲线距离求解

C蓝桥杯皮亚诺曲线距离求解 一、题目概述二、解题分析2.1解题思路2.2k值范围限制 三、实现代码四、代码测试4.1蓝桥杯测试平台4.2直接传入原始输入的k值4.3限制k值大小4.4pow函数求整数高次幂存在误差4.5满分代码 附录error: ‘long long int y1’ redeclared as different kin…...

LabVIEW伺服阀高频振动测试

在伺服阀高频振动测试中&#xff0c;闭环控制系统的实时性与稳定性至关重要。针对用户提出的1kHz控制频率需求及Windows平台兼容性问题&#xff0c;本文重点分析NI PCIe-7842R实时扩展卡的功能与局限性&#xff0c;并提供其他替代方案的综合对比&#xff0c;以帮助用户选择适合…...

Linux 》》Ubuntu 18 LTS 之后的版本 修改IP地址 主机名

进入目录 /etc/netplan 修改 50-cloud-init.yaml 》保存文件后&#xff0c;执行以下命令应用更改&#xff1a; sudo netplan apply 》》 DHCP模式 修改主机名 hostnamectl set-hostname xxxx 修改cloud.cfg 防止重启主机名还原 但测试下来 不修改&#xff0c; 重启 也不会还…...

使用OpenCV和MediaPipe库——抽烟检测(姿态监控)

目录 抽烟检测的运用 1. 安全监控 (1) 公共场所禁烟监管 (2) 工业安全 2. 智能城市与执法 (1) 城市违章吸烟检测 (2) 无人值守管理 3. 健康管理与医疗 (1) 吸烟习惯分析 (2) 远程监护 4. AI 监控与商业分析 (1) 保险行业 (2) 商场营销 5. 技术实现 (1) 计算机视…...

为什么要使用前缀索引,以及建立前缀索引:sql示例

背景&#xff1a; 你想啊&#xff0c;数据库里有些字段&#xff0c;它老长了&#xff0c;就像那种 varchar(255) 的字段&#xff0c;这玩意儿要是整个字段都拿来建索引&#xff0c;那可太占地方了。打个比方&#xff0c;这就好比你要在一个超级大的笔记本上记东西&#xff0c;每…...

Android UDP广播与监听

在Android中&#xff0c;UDP广播和监听可以通过DatagramSocket和DatagramPacket来实现。UDP广播允许你将数据包发送到网络中的所有设备&#xff0c;而监听则允许你接收这些广播数据包。 1. 发送UDP广播 要发送UDP广播&#xff0c;你需要创建一个DatagramSocket&#xff0c;并使…...

谷粒商城:性能压测JVM堆区

目录 Kit Apache JMeter VisualVM 堆内存 jvm内存模型 垃圾回收&#xff08;Garbage Collection, GC&#xff09; 新对象分配内存 GC步骤 MinorGC 性能优化 影响因素 优化 nginx动静分离 优化三级分类获取 Jvm参数配置堆区 测试 Kit Apache JMeter 压力测试&…...

Redis项目_黑马点评

部署: 1. 导入sql 开发: Session登录: session的原理是cookie,每个session都有个唯一的sessionId, 在每次访问tomcat的时候sessionId就会自动的写在cookie当中, 携带着sessionId就能找到session, 所以不需要返回用户凭证 每一个进入tomcat的请求都是有一个独立的线程来处理…...

Golang Channel 使用详解、注意事项与死锁分析

#作者&#xff1a;西门吹雪 文章目录 一、引言&#xff1a;Channel 在 Go 并发编程中的关键地位二、Channel 基础概念深度剖析2.1 独特特性2.2 类型与分类细解 三、Channel 基本使用实操指南3.1 声明与初始化3.3 单向 Channel 的运用 四、Channel 典型使用场景实战案例4.1 协程…...

CSS 入门指南(一):基本概念 选择器 常用元素属性

一、初识 CSS 1, CSS 定义 层叠样式表(Cascading Style Sheets&#xff0c;缩写为 CSS)&#xff0c;是一种 样式表 语言&#xff0c;用来描述 HTML 文档的呈现&#xff08;美化内容&#xff09; CSS 能够对网页中元素位置的排版进行 像素级 精确控制&#xff0c;实现美化页面…...