【Go - 10分钟,快速搭建一个简易日志回传系统】

上周一个平凡的工作日傍晚,快要下班的时候,客户端新产品线负责人突然火急火燎的找到我 ,说新的APP马上要release了,发现还少个APP异常崩溃时,用户上报日志的功能 ,需要后端支持,提供个日志回传接口。

时间紧,立刻开始行动。提供个接口 ,自然不是难题,但是只需要提供一个接口吗?我知道这很急,但先别急,

流程

先来拆解下这个需求,用户从APP上报问题日志后 ,要有个服务接收然后存储,存储完 后续对应研发 还要能进行检索查看,所以整体流程。

这其中就涉及到,

日志回传服务

  • http 上传接口
  • 接口身份验证 (多选一)
    • ak、sk
    • 静态token

日志检索

  • 日志检索
  • 日志查看
  • 用户权限

部署

  • 固定域名
    • 日志回传服务 需要一个固定域名
  • 服务运行环境 (多选一)
    • 物理机
    • serverless

任务不重,但时间紧。废话不多说,需求清晰了,啪啪啪几下,先出个实现方案,这里我们以填空的方式 把实现填到上面的流程上。

实现

日志回传服务可以搭建一个http服务,日志文件上传Post 提交表单的形式。

日志存储可以选用 阿里云oss存储, ES等,甚至可以直接放到本地。

日志检索可以依赖 阿里云oss控制台,权限管理,查看都有对应配套。

那么接下来,上代码

代码

http 服务器,搭建一个简易日志回传服务

package main

import (
	"fmt"
	"mime/multipart"
	"net/http"
	"os"

	"github.com/gin-gonic/gin"
)

func handleError(err error) {
	fmt.Println("Error:", err)
	os.Exit(-1)
}

func Auth() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取请求头中的Token
		token := c.GetHeader("Token")
		if token == "" {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "Token is required"})
			c.Abort()
			return
		}

		// 验证Token是否有效
		if token != "my_token" {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid Token"})
			c.Abort()
			return
		}

		// 继续往下处理
		c.Next()
	}
}

func saveToOSS(c *gin.Context, file *multipart.FileHeader) error {
	// Init oss client
	client := getSingletonOssClient()
	// yourBucketName填写存储空间名称。
	bucketName := "${your_bucket_name}"
	// yourObjectName填写Object完整路径,完整路径不包含Bucket名称。
	objectPath := "${path}"
	// 获取存储空间。
	bucket, err := client.Bucket(bucketName)
	if err != nil {
		handleError(err)
	}

	// 临时保存文件到本地
	filePath := "./uploads/" + file.Filename
	err = c.SaveUploadedFile(file, filePath)
	// 上传完成后删除文件
	defer os.Remove(filePath)
	if err != nil {
		return err
	}
	// 上传文件到OSS
	objectName := objectPath + "/" + file.Filename
	err = bucket.PutObjectFromFile(objectName, filePath)
	if err != nil {
		return err
	}
	return nil
}

func main() {
	router := gin.Default()

	router.Use(Auth())

	// 定义文件上传的POST接口
	router.POST("/upload", func(c *gin.Context) {
		// 从请求中获取文件
		file, err := c.FormFile("file")
		if err != nil {
			c.String(http.StatusBadRequest, fmt.Sprintf("get form err: %s", err.Error()))
			return
		}
		// 这里存储方式,选择存储到阿里云OSS
		err = saveToOSS(c, file)
		if err != nil {
			c.String(http.StatusInternalServerError, fmt.Sprintf("upload file err: %s", err.Error()))
			return
		}
		c.String(http.StatusOK, fmt.Sprintf("File %s uploaded successfully.", file.Filename))
	})

	router.Run(":8080")
}

存储层,这里选用阿里云OSS

package main

import (
	"fmt"
	"os"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func getSingletonOssClient() *oss.Client {
	// 填写你自己的AK
	os.Setenv("OSS_ACCESS_KEY_ID", "${your_ak}")
	// 填写你自己的SK
	os.Setenv("OSS_ACCESS_KEY_SECRET", "${your_sk}")

	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(-1)
	}
	// 创建OSSClient实例。
	// yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,
	// 填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
	endpoint := "<https://oss-cn-hangzhou.aliyuncs.com>"
	client, err := oss.New(endpoint, "", "", oss.SetCredentialsProvider(&provider))
	if err != nil {
		handleError(err)
	}
	fmt.Printf("client:%#v\\n", client)
	return client

}

至此便快速搭建了一个简易的日志回传系统, 调用试一下

curl -X POST <http://localhost:8080/upload> -F "file=@/${your_log_path}/a.log" -H "Token: my_token"

OK,完成回传。


相关推荐
机器之心2 小时前
图学习新突破:一个统一框架连接空域和频域
人工智能·后端
.生产的驴2 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
顽疲3 小时前
springboot vue 会员收银系统 含源码 开发流程
vue.js·spring boot·后端
机器之心3 小时前
AAAI 2025|时间序列演进也是种扩散过程?基于移动自回归的时序扩散预测模型
人工智能·后端
hanglove_lucky4 小时前
本地摄像头视频流在html中打开
前端·后端·html
皓木.5 小时前
(自用)配置文件优先级、SpringBoot原理、Maven私服
java·spring boot·后端
i7i8i9com5 小时前
java 1.8+springboot文件上传+vue3+ts+antdv
java·spring boot·后端
秋意钟5 小时前
Spring框架处理时间类型格式
java·后端·spring
我叫啥都行6 小时前
计算机基础复习12.22
java·jvm·redis·后端·mysql
Stark、6 小时前
【Linux】文件IO--fcntl/lseek/阻塞与非阻塞/文件偏移
linux·运维·服务器·c语言·后端