蓝牙通讯数据传输,蓝牙UUID,BluetoothAdapter;adb input 模拟系统输入,adb logcat:抓包,抓日志,蓝牙通讯,adb命令实现

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 蓝牙通讯数据传输,蓝牙UUID,BluetoothAdapter;adb input 模拟系统输入,adb logcat:抓包,抓日志,蓝牙通讯,adb命令实现

adb 命令 模拟滑动



input text
input keyevent
input tap
input swipe


  1. keyevent指的是android对应的keycode,比如home键的keycode=3,back键的keycode=4.


具体:  Android Keycode详解_小小攻城师的博客-CSDN博客_android keycode


举例:模拟home按键:adb shell input keyevent 3


  1. 关于tap的话,他模拟的是touch屏幕的事件,只需给出x、y坐标即可。


此x、y坐标对应的是真实的屏幕分辨率,所以要根据具体手机具体看,比如你想点击屏幕(x, y) = (250, 250)位置:


adb shell input tap 250 250


  1. 关于swipe同tap是一样的,只是他是模拟滑动的事件,给出起点和终点的坐标即可。例如从屏幕(250, 250), 到屏幕(300, 300)即

adb shell input swipe 250 250 300 300


还可以使用:android MotionEvent.obtain模拟事件


public static final int ACTION_DOWN = 0;
public static final int ACTION_HOVER_ENTER = 9;
public static final int ACTION_HOVER_EXIT = 10;
public static final int ACTION_HOVER_MOVE = 7;
public static final int ACTION_MOVE = 2;
复制代码
final long downTime = SystemClock.uptimeMillis();
                final MotionEvent downEvent = MotionEvent.obtain(
                        downTime, downTime, MotionEvent.ACTION_DOWN, 200, 200, 0);
                final MotionEvent upEvent = MotionEvent.obtain(
                        downTime, SystemClock.uptimeMillis() + 10, MotionEvent.ACTION_UP, 200, 200, 0);
                if (mDocView != null) {
                    mDocView.onTouchEvent(downEvent);
                    mDocView.onTouchEvent(upEvent);
                }
                downEvent.recycle();
                upEvent.recycle();

蓝牙相关知识



UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,那么怎么才能生成这样的一串数字呢?下面就讲讲怎么生成这个数字。


BluetoothAdapter



ef8003f2569e47e5b8ddabca43ee322f_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


BluetoothAdapter——本地设备,对蓝牙操作首先就需要有一个BluetoothAdapter实例。常用的几个方法如下:


cancelDiscovery()——取消本地蓝牙设备的搜索操作,如果本地设备正在进行搜索,那么调用该方法后将停止搜索操作。


Disable()——关闭蓝牙设备。


Enable()——打开蓝牙设备。相信大家都有过打开蓝牙的经历,一般情况下都会弹出一个窗口,说正在请求打开蓝牙设备


getAddress()——获取蓝牙设备的MAC地址。


GetDefaultAdapter()——获取本地的蓝牙设备


getName()——获取本地蓝牙的名称


getRemoteDevice(String address)——根据远程设备的MAC地址来获取远程设备


startDiscovery()——蓝牙设备开始搜索周边设备


BuletoothDevice——远程设备。


// 获取本地的蓝牙适配器实例
             BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
             if(adapter!=null)
             {
                 if(!adapter.isEnabled())
                 {
                     //通过这个方法来请求打开我们的蓝牙设备
                     Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                     startActivity(intent);
                 }
             }
             else
             {
                 System.out.println("本地设备驱动异常!");
             }

配对一般都是发现设备后,由我们人工来选择配对。可以通过方法来获得配对的设备:



//通过getBondedDevices方法来获取已经与本设备配对的设备
                 Set<BluetoothDevice> device= adapter.getBondedDevices();
                 if(device.size()>0)
                 {
                     for(Iterator iterator=device.iterator();iterator.hasNext();)
                     {
                         BluetoothDevice bluetoothDevice=(BluetoothDevice)iterator.next();
                         System.out.println(bluetoothDevice.getAddress());
                     }
                 }

数据交换,首先是进行连接,在进行数据传输:



连接:


/**
     * 客户端主动发起连接,去连接服务端
     *
     * @param serviceDevice 服务端的蓝牙设备
     */
    public void connect(BluetoothDevice serviceDevice) {
        if (mTargThread != null) {
            mTargThread.cancle();
        }
        if (mDataThread != null) {
            mDataThread.cancle();
        }
        mTargThread = new BlueClientThread(serviceDevice, mSocketHandler);
        mTargThread.start();
    }
//另一个服务线程
    public BlueClientThread(BluetoothDevice serviceDevice, Handler handler) {
        super(handler);
        mServiceDevice = serviceDevice;
    }
    @Override
    public void run() {
        super.run();
        if (!isRunning) return;
        try {
            sendMessage(BlueSocketStatus.CONNECTIONING);
            mBlueSocket = mServiceDevice.createRfcommSocketToServiceRecord(UUID_ANDROID_DEVICE);
            mBlueSocket.connect();
            sendMessage(BlueSocketStatus.ACCEPTED);
        } catch (IOException e) {
            sendMessage(BlueSocketStatus.DISCONNECTION);
        }
    }
//关键sendmessage
    public void sendMessage(BlueSocketStatus status) {
        if (mHandler != null && isRunning)
            mHandler.obtainMessage(status.ordinal()).sendToTarget();//ordinal  :序数
    }
    public void sendMessage(BlueSocketStatus status, Object object) {
        if (mHandler != null && isRunning)
            mHandler.obtainMessage(status.ordinal(), object).sendToTarget();
//获取message并发送
    }

关键就是:


sendMessage(BlueSocketStatus.CONNECTIONING);
mBlueSocket = mServiceDevice.createRfcommSocketToServiceRecord(UUID_ANDROID_DEVICE);
mBlueSocket.connect();

1e7f22eebe5344159df15faa7b51c558_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

进行连接:


8a17acc0d6614d0ab533c06141e83267_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png


接下来就是发送数据:


private ConcurrentLinkedQueue<IMessage> mQueue = new ConcurrentLinkedQueue<>();
    public synchronized boolean write(IMessage message) {
        message.toString();
        if (mNowStatus == BlueSocketBaseThread.BlueSocketStatus.CONNEDTIONED) {
            synchronized (BluetoothSppHelper.class) {
                if (mNowStatus == BlueSocketBaseThread.BlueSocketStatus.CONNEDTIONED) {
                    mQueue.add(message);
                    mDataThread.startQueue();
                    return true;
                }
                return false;
            }
        }
        return false;
    }

补充1:ConcurrentLinkedQueue:Java并发编程;


在并发编程中我们有时候需要使用线程安全的队列。如果我们要实现一个线程安全的队列有两种实现方式


  1. 一种是使用阻塞算法
  2. 另一种是使用非阻塞算法。
  • 使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现
  • 非阻塞的实现方式则可以使用循环CAS的方式来实现,下面我们一起来研究下Doug Lea是如何使用非阻塞的方式来实现线程安全队列ConcurrentLinkedQueue的。


ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。它采用了“wait-free”算法来实现,该算法在Michael & Scott算法上进行了一些修改。


补充2:createRfcommSocketToServiceRecord,listenUsingRfcommWithServiceRecord


服务端


通过调用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法来获取BluetoothServerSocket(UUID用于客户端与服务端之间的配对)


BluetoothServerSocket serverSocket = mAdapter.listenUsingRfcommWithServiceRecord(serverSocketName,UUID);
serverSocket.accept();

客户端:UUID 是 通用唯一识别码(Universally Unique Identifier)


调用BluetoothService的createRfcommSocketToServiceRecord(UUID)方法获取BluetoothSocket(该UUID应该同于服务端的UUID)。


调用BluetoothSocket的connect()方法(该方法为block方法),如果UUID同服务端的UUID匹配,并且连接被服务端accept,则connect()方法返回。


BluetoothServerSocket和BluetoothSocket两个类来建立Server端和Client端,还需要使用到一些关于流(Stream)的知识。


BluetoothServerSocket——服务端(监听端、监听器、接受请求的一端)


Accept()——阻塞宿主线程,直至收到客户端请求。返回BluetoothSocket对象。由于这个


Accept(int timeout)——阻塞宿主线程,直至收到客户端请求或等待时间超过timeout。返回BluetoothSocket对象。


Close()——关闭BluetoothServerSocket监听器。


可以看到,Accept方法是一个阻塞方法,所以在进行开发的时候,一般都需要用到多线程的知识。JAVA的多线程知识,可以在JAVA的JDK帮助文档中查看,就单纯的应用来说还是比较简单的。


BluetoothSocket——客户端(请求端)


Close()——关闭BluetoothSocket请求端。


Connect()——主动向服务端(监听端)发起连接请求。


如果一个设备需要和两个或多个设备连接时,就需要作为一个server来传输,服务器端套接字在接受(accepted) 一个客户发来的BluetoothSocket连接请求时作出相应的响应。服务器socket将监听进入的连接请求,一旦连接被接受,将产生一个BluetoothSocket。


创建一个Server


使用BluetoothAdapter类的listenUsingRfcommWithServiceRecord方法来新建一个ServerSocket。在listenUsingRfcommWithServiceRecord中有一个参数叫做UUID,UUID(Universally Unique Identifier)是一个128位的字符串ID,被用于唯一标识我们的蓝牙服务。你可以使用web上的任何一款UUID产生器为你的程序获取一个UUID,然后使用fromString(String)初始化一个UUID。

  

使用ServerSocket实例的accept方法进行监听,当监听到带有我们初始化的UUID参数的连接请求后作出响应,连接成功后返回一个BluetoothSocket对象。连接完成后,调用close方法关闭该Socket监听。


// Bluetooth的ServerSocket包装类
     class BluetoothServer {
         public BluetoothServer() throws IOException {
         }
         // 要建立一个ServerSocket对象,需要使用adapter.listenUsingRfcommWithServiceRecord方法
 // UUID可以在网上去申请
         private BluetoothServerSocket serverSocket = adapter.listenUsingRfcommWithServiceRecord("myServerSocket",
                         UUID.fromString("84D1319C-FBAF-644C-901A-8F091F25AF04"));
         BluetoothSocket socket = serverSocket.accept();
         void m() throws IOException {
             if (socket != null) {
                 InputStream inputStream = socket.getInputStream();
                 int read = -1;
                 final byte[] bytes = new byte[1024];
                 for (; (read = inputStream.read(bytes)) > -1;) {
                     final int count = read;
                     Thread _start = new Thread(new Runnable() {
                         @Override
                         public void run() { 
                             // TODO Auto-generated method stub
                             StringBuilder sb = new StringBuilder();
                             for (int i = 0; i < count; i++) {
                                 if (i > 0) {
                                     sb.append(' ');
                                 }
                                 String _s = Integer.toHexString(bytes[i] & 0xFF);
                                 if (_s.length() < 2) {
                                     sb.append('0');
                                 }
                                 sb.append(_s);
                             }
                             System.out.println(sb.toString());
                         }
                     });
                     _start.start();
                 }
             }
         }
     }

创建一个Client   



创建一个Client端,首先需要我们使用BluetoothDevice的实例的createRfcommSocketToServiceRecord方法来创建一个BluetoothSocket实例。在创建的时候,需要给createRfcommSocketToServiceRecord方法传入我们服务端的UUID值。然后使用BluetoothSocket实例的Connect方法对Server端进行连接请求,当连接成功后,Client端和Server端的传输通道就被打开。最后在连接完成后使用该实例的close方法来关闭这个连接。


class BluetoothClient {
         BluetoothDevice device = null;
         //通过构造函数来传入一个BluetoothDevice实例
         public BluetoothClient(BluetoothDevice device) {
             this.device = device;
         }
         BluetoothSocket socket = null;
         void connetServer() throws IOException {
             Thread _clientThread = new Thread(new Runnable() {
                 public void run() {
                     try {
                         //通过BluetoothDevice实例的createRfcommSocketToServiceRecord方法可以返回一个带有UUID的BluetoothSocket实例
                         socket = device.createRfcommSocketToServiceRecord(UUID.fromString("84D1319C-FBAF-644C-901A-8F091F25AF04"));
                     } catch (IOException e1) { 
                         // TODO Auto-generated catch block
                         e1.printStackTrace();
                     }
                     try {
                         socket.connect();
                     } catch (IOException e1) { 
                         // TODO Auto-generated catch block
                         e1.printStackTrace();
                     }
                     if (socket != null) {
                         try {
                             socket.close();
                         } catch (Exception e) {
                             // TODO: handle exception
                         }
                     }
                 }
             });
             _clientThread.start();
         }
     }

getInputStream()——获得一个可读的流,该流在连接不成功的情况下依旧可以获得,但是对其操作的话就会报IOException的异常。需要从外部获取的数据都从该流中获取。


getOutputStrem()——获得一个可写的流,该流在连接不成功的情况下依旧可以获得,但是对其操作的话就会报IOException的异常。需要往外部传输的数据都可以写到该流中传输出去。


数据传输的大致流程如下:



首先,分别通过getInputStream()和getOutputStream()获得管理数据传输的InputStream和OutputStream。


然后,开辟一个线程专门用于数据的读或写。这是非常重要的,因为read(byte[])和write(byte[])方法都是阻塞调用。read(byte[])从输入流(InputStream)中读取数据。write(byte[])将数据写入到OutputStream流中去,这个方法一般不会阻塞,但当远程设备的中间缓冲区已满而对方没有及时地调用read(byte[])时将会一直阻塞。所以,新开辟的线程中的主循环将一直用于从InputStream中读取数据。


还要补充一点,由于蓝牙设备是系统设备,所以需要有相应的权限支持。在AndroidManifest.xml文件中添加上权限。


<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>

蓝牙通讯数据传输



蓝牙通讯用android 的api获取看牙设备进行连接,之后进行数据传输,建立各线程;设置监听,进行数据接受监听和状态监听;


数据传输都是以 流的方式进行;


不管是图片,视频还是直接的文字,都是转化成byte,再用数据流进行传输;


图片视频是以文件的形式,再转成byte,再加上头尾校验位,长度等等,再用流进行读写,流已经是Android给我们弄好的了;

 

private File mContent;   
FileInputStream fio = new FileInputStream(mContent);
private String mExtend;
    @Override
    public byte[] creatHeader() {
        byte[] extend = mExtend.getBytes();
        byte[] length = TypeUtils.longToBytes(getLength());
        byte[] header = new byte[10 + extend.length];
        header[0] = HEADER;                                         //魔数
        header[1] = getType();                                     //类型
        System.arraycopy(length, 0, header, 2, length.length);     //长度
        System.arraycopy(extend, 0, header, 10, extend.length);     //扩展信息
        return header;
    }
    private File mContent;
    public void writeContent(OutputStream outputStream) throws IOException {
        outputStream.write(creatHeader());
        outputStream.write(0xA);
        outputStream.write(0xD);
        FileInputStream fio = new FileInputStream(mContent);
        byte[] buffer = new byte[64 * 1024];
        int length = 0;
        while ((length = fio.read(buffer)) >= 0) {
            outputStream.write(buffer, 0, length);
            outputStream.flush();
        }
    }

string,int 等形式就是直接转成byte,再加上头尾校验位,长度等等,再用流进行读写;

  outputStream.write(creatHeader());

private String mExtend;
    @Override
    public byte[] creatHeader() {
        byte[] extend = mExtend.getBytes();
        byte[] length = TypeUtils.longToBytes(getLength());
        byte[] header = new byte[10 + extend.length];
        header[0] = HEADER;                                         //魔数
        header[1] = getType();                                     //类型
        System.arraycopy(length, 0, header, 2, length.length);     //长度
        System.arraycopy(extend, 0, header, 10, extend.length);     //扩展信息
        return header;
    }
   public void writeContent(OutputStream outputStream) throws IOException {
        outputStream.write(creatHeader());
        outputStream.write(0xA);
        outputStream.write(0xD);
        outputStream.write(contentByte);
    }

adb logcat:抓包,抓日志



adb logcat | find  "com.itep.bluetoothsocketservice" C:/hehe.txt

adb logcat 仅仅是输出应用的log信息;而不是android的系统日志;


adb input 模拟系统输入



KEYCODE_CALL 进入拨号盘 5

KEYCODE_ENDCALL 挂机键 6

KEYCODE_HOME 按键Home 3

KEYCODE_MENU 菜单键 82

KEYCODE_BACK 返回键 4

KEYCODE_SEARCH 搜索键 84

KEYCODE_CAMERA 拍照键 27

KEYCODE_FOCUS 拍照对焦键 80

KEYCODE_POWER 电源键 26

KEYCODE_NOTIFICATION 通知键 83

KEYCODE_MUTE 话筒静音键 91

KEYCODE_VOLUME_MUTE 扬声器静音键 164

KEYCODE_VOLUME_UP 音量增加键 24

KEYCODE_VOLUME_DOWN 音量减小键 25


控制键


KEYCODE_ENTER 回车键 66

KEYCODE_ESCAPE ESC键 111

KEYCODE_DPAD_CENTER 导航键 确定键 23

KEYCODE_DPAD_UP 导航键 向上 19

KEYCODE_DPAD_DOWN 导航键 向下 20

KEYCODE_DPAD_LEFT 导航键 向左 21

KEYCODE_DPAD_RIGHT 导航键 向右 22

KEYCODE_MOVE_HOME 光标移动到开始键 122

KEYCODE_MOVE_END 光标移动到末尾键 123

KEYCODE_PAGE_UP 向上翻页键 92

KEYCODE_PAGE_DOWN 向下翻页键 93

KEYCODE_DEL 退格键 67

KEYCODE_FORWARD_DEL 删除键 112

KEYCODE_INSERT 插入键 124

KEYCODE_TAB Tab键 61

KEYCODE_NUM_LOCK 小键盘锁 143

KEYCODE_CAPS_LOCK 大写锁定键 115

KEYCODE_BREAK Break/Pause键 121

KEYCODE_SCROLL_LOCK 滚动锁定键 116

KEYCODE_ZOOM_IN 放大键 168

KEYCODE_ZOOM_OUT 缩小键 169

利用命令“adb shell input keyevent <键值>”可以实现自动化。例如“adb shell input keyevent 3”就可以按下Home键。]

执行返回:adb shell input keyevent 4

执行灭屏亮屏:adb shell input keyevent 26

执行解锁屏幕:adb shell input keyevent 82


3 HOME 键
4 返回键
5 打开拨号应用
6 挂断电话
24 增加音量
25 降低音量
26 电源键
27 拍照(需要在相机应用里)
64 打开浏览器
82 菜单键
85 播放/暂停
86 停止播放
87 播放下一首
88 播放上一首
122 移动光标到行首或列表顶部
123 移动光标到行末或列表底部
126 恢复播放
127 暂停播放
164 静音
176 打开系统设置
187 切换应用
207 打开联系人
208 打开日历
209 打开音乐
210 打开计算器
220 降低屏幕亮度
221 提高屏幕亮度
223 系统休眠
224 点亮屏幕
231 打开语音助手
276 如果没有 wakelock 则让系统休眠


蓝牙通讯和adb命令实现手机之间互相操作:adb命令24 是音量增加。


c1730f86b6d5402d8d1cb245f9c7175a_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.jpg


4b80f5f9a5a04c7fa53d8a36ba08ff28_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.jpg

虚拟按键通过AccessibilityService进行控制,实际就是一个service,实现button,监听系统暴露的Api:


d37adbb7cb344334adc6fa60035094e1_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.jpg

fe93fbc1de6c46f28d1a2e8be64582f3_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.jpg

eeb65b3a581541ceb8a67c06d4ef1164_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.jpg

源码就是在github上,自己拉下;


相关实践学习
自建数据库迁移到云数据库
本场景将引导您将网站的自建数据库平滑迁移至云数据库RDS。通过使用RDS,您可以获得稳定、可靠和安全的企业级数据库服务,可以更加专注于发展核心业务,无需过多担心数据库的管理和维护。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
相关文章
WGLOG日志管理系统是怎么收集日志的
WGLOG通过部署Agent客户端采集日志,Agent持续收集指定日志文件并上报Server,Server负责展示与分析。Agent与Server需保持相同版本。官网下载地址:www.wgstart.com
|
10月前
|
Prometheus 监控 Cloud Native
基于docker搭建监控系统&日志收集
Prometheus 是一款由 SoundCloud 开发的开源监控报警系统及时序数据库(TSDB),支持多维数据模型和灵活查询语言,适用于大规模集群监控。它通过 HTTP 拉取数据,支持服务发现、多种图表展示(如 Grafana),并可结合 Loki 实现日志聚合。本文介绍其架构、部署及与 Docker 集成的监控方案。
874 122
基于docker搭建监控系统&日志收集
|
监控 API 开发工具
HarmonyOS Next的HiLog日志系统完全指南:从入门到精通
本文深入解析HarmonyOS Next的HiLog日志系统,涵盖日志级别、核心API、隐私保护与高级回调功能,助你从入门到精通掌握这一重要开发工具。
|
10月前
|
Ubuntu
在Ubuntu系统上设置syslog日志轮替与大小限制
请注意,在修改任何系统级别配置之前,请务必备份相应得原始档案并理解每项变更可能带来得影响。
1175 2
|
存储 前端开发 数据可视化
Grafana Loki,轻量级日志系统
本文介绍了基于Grafana、Loki和Alloy构建的轻量级日志系统。Loki是一个由Grafana Labs开发的日志聚合系统,具备高可用性和多租户支持,专注于日志而非指标,通过标签索引而非内容索引实现高效存储。Alloy则是用于收集和转发日志至Loki的强大工具。文章详细描述了系统的架构、组件及其工作流程,并提供了快速搭建指南,包括准备步骤、部署命令及验证方法。此外,还展示了如何使用Grafana查看日志,以及一些基本的LogQL查询示例。最后,作者探讨了Loki架构的独特之处,提出了“巨型单体模块化”的概念,即一个应用既可单体部署也可分布式部署,整体协同实现全部功能。
6011 70
Grafana Loki,轻量级日志系统
WGLOG日志管理系统可以采集网络设备的日志吗
WGLOG日志审计系统提供开放接口,支持外部获取日志内容后发送至该接口,实现日志的存储与分析。详情请访问:https://www.wgstart.com/wglog/docs9.html
|
存储 消息中间件 缓存
MiniMax GenAI 可观测性分析 :基于阿里云 SelectDB 构建 PB 级别日志系统
基于阿里云SelectDB,MiniMax构建了覆盖国内及海外业务的日志可观测中台,总体数据规模超过数PB,日均新增日志写入量达数百TB。系统在P95分位查询场景下的响应时间小于3秒,峰值时刻实现了超过10GB/s的读写吞吐。通过存算分离、高压缩比算法和单副本热缓存等技术手段,MiniMax在优化性能的同时显著降低了建设成本,计算资源用量降低40%,热数据存储用量降低50%,为未来业务的高速发展和技术演进奠定了坚实基础。
719 1
MiniMax GenAI 可观测性分析 :基于阿里云 SelectDB 构建 PB 级别日志系统
|
存储 JSON Go
PHP 日志系统的最佳搭档:一个 Go 写的远程日志收集服务
为了不再 SSH 上去翻日志,我写了个 Go 小脚本,用来接收远程日志。PHP 负责记录日志,Go 负责存储和展示,按天存储、支持 API 访问、可远程管理,终于能第一时间知道项目炸了。
381 10
|
存储 安全 Java
Spring Boot 3 集成Spring AOP实现系统日志记录
本文介绍了如何在Spring Boot 3中集成Spring AOP实现系统日志记录功能。通过定义`SysLog`注解和配置相应的AOP切面,可以在方法执行前后自动记录日志信息,包括操作的开始时间、结束时间、请求参数、返回结果、异常信息等,并将这些信息保存到数据库中。此外,还使用了`ThreadLocal`变量来存储每个线程独立的日志数据,确保线程安全。文中还展示了项目实战中的部分代码片段,以及基于Spring Boot 3 + Vue 3构建的快速开发框架的简介与内置功能列表。此框架结合了当前主流技术栈,提供了用户管理、权限控制、接口文档自动生成等多项实用特性。
1282 8
|
存储 监控 安全
5款 Syslog集中系统日志常用工具对比推荐
集中管理Syslog有助于持续监控网络中的恶意活动,确保日志的搜索和分析更为便捷。常用工具包括Rsyslog、Syslog-ng、Logstash和Fluentd,它们各有优劣。Rsyslog通过多种协议确保日志传输的安全性;Syslog-ng支持高效收集和转发日志;Logstash能解析多源日志并索引;Fluentd将日志转换为JSON格式。卓豪EventLog Analyzer则提供一体化的日志管理,支持日志分析、报表生成、用户行为分析及实时告警,是全面的日志管理解决方案。
555 0