diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 00000000..468af259 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,574 @@ +### 安装说明 + + +### 方式一. 手动安装(推荐) + +克隆代码库 + + ```sh + git clone https://github.com/rocboss/paopao-ce.git + ``` + +#### 后端 + +1. 导入项目根目录下的 `scripts/paopao.sql` 文件至MySQL数据库 +2. 拷贝项目根目录下 `config.yaml.sample` 文件至 `config.yaml`,按照注释完成配置编辑 +3. 编译后端 + 编译api服务: + ```sh + make build + ``` + 编译api服务、内嵌web前端ui: + ```sh + make build + ``` + 也可以使用精简模式编译,不内嵌web前端ui: + ```sh + make build TAGS='slim embed' + ``` + 编译后在`release`目录可以找到对应可执行文件。 + ```sh + release/paopao + ``` + +4. 直接运行后端 + 运行api服务: + ```sh + make run + ``` + 运行api服务、web前端ui服务: + ```sh + make run TAGS='embed' + ``` + 提示: 如果需要内嵌web前端ui,请先构建web前端(建议设置web/.env为VITE_HOST="")。 + +5. 使用内置的Migrate机制自动升级维护SQL DDL: + ```sh + # 添加 Migration 功能到 Features 中 开启migrate功能 + vim config.yaml + # file: config.yaml + # Features: + # Default: ["Base", "MySQL", "Zinc", "MinIO", "LoggerZinc", "Migration"] + + # 编译时加入migration tag编译出支持migrate功能的可执行文件 + make build TAGS='migration' + release/paopao + + # 或者 带上migration tag直接运行 + make run TAGS='migration' + ``` + > 注意:默认编译出来的可执行文件是不内置migrate功能,需要编译时带上migration tag才能内置支持migrage功能。 + + +#### 前端 + +1. 进入前端目录 `web`,拷贝`.env` 到 `.env.local`,编辑 `.env.local ` 文件中后端服务地址及其他配置项,下载依赖包 + + ```sh + cd ./web && cp .env .env.local + vim .env.local + yarn + ``` + +2. 编译前端 + + ```sh + yarn build + ``` + + build完成后,可以在dist目录获取编译产出,配置nginx指向至该目录即可 + +#### 桌面端 + +1. 进入前端目录 `web`,拷贝`.env` 到 `.env.local`,编辑 `.env.local ` 文件中后端服务地址及其他配置项,下载依赖包 + + ```sh + cd ./web && cp .env .env.local + vim .env.local + yarn + ``` + +2. 编译前端 + + ```sh + yarn build + ``` + +3. 构建桌面端 + ```sh + yarn tauri build + ``` + 桌面端是使用[Rust](https://www.rust-lang.org/) + [tauri](https://github.com/tauri-apps/tauri)编写 + 的,需要安装tauri的依赖,具体参考[https://tauri.studio/v1/guides/getting-started/prerequisites](https://tauri.studio/v1/guides/getting-started/prerequisites). + + +### 方式二. 使用Docker构建、运行 + * 后端: + ```sh + # 默认参数构建, 默认内嵌web ui并设置api host为空 + docker build -t your/paopao-ce:tag . + + # 内嵌web ui并且自定义API host参数 + docker build -t your/paopao-ce:tag --build-arg API_HOST=http://api.paopao.info . + + # 内嵌web ui并且使用本地web/.env中的API host + docker build -t your/paopao-ce:tag --build-arg USE_API_HOST=no . + + # 内嵌web ui并且使用本地编译的web/dist构建 + docker build -t your/paopao-ce:tag --build-arg USE_DIST=yes . + + # 只编译api server + docker build -t your/paopao-ce:tag --build-arg EMBED_UI=no . + + # 运行 + mkdir custom && docker run -d -p 8008:8008 -v ${PWD}/custom:/app/paopao-ce/custom -v ${PWD}/config.yaml.sample:/app/paopao-ce/config.yaml your/paopao-ce:tag + + # 或者直接运行构建好的docker image + mkdir custom && docker run -d -p 8008:8008 -v ${PWD}/custom:/app/paopao-ce/custom -v ${PWD}/config.yaml.sample:/app/paopao-ce/config.yaml bitbus/paopao-ce:latest + ``` + + * 前端: + ```sh + cd web + + # 默认参数构建 + docker build -t your/paopao-ce:web . + + # 自定义API host 参数构建 + docker build -t your/paopao-ce:web --build-arg API_HOST=http://api.paopao.info . + + # 使用本地编译的dist构建 + docker build -t your/paopao-ce:web --build-arg USE_DIST=yes . + + # 运行 + docker run -d -p 8010:80 your/paopao-ce:web + ``` + + * All-In-One: + ```sh + # 构建Image + docker buildx build --build-arg USE_DIST="yes" -t your/paopao-ce:all-in-one-latest -f Dockerfile.allinone . + + # 运行 + docker run --name paopao-ce-allinone -d -p 8000:8008 -p 7700:7700 -v ./data/custom:/app/custom -v ./data/meili_data:/app/meili_data your/paopao-ce:all-in-one-latest + + # 或者使用官方Image运行 + docker run --name paopao-ce-allinone -d -p 8000:8008 -p 7700:7700 -v ./data/custom:/app/custom -v ./data/meili_data:/app/meili_data bitbus/paopao-ce:all-in-one-latest + + # 或者使用官方Image运行 + 自定义config.yaml + docker run --name paopao-ce-allinone -d -p 8000:8008 -p 7700:7700 -v ./config.yaml:/app/config.yaml -v ./data/custom:/app/custom -v ./data/meili_data:/app/meili_data bitbus/paopao-ce:all-in-one-latest + ``` + > 注意在`config.yaml` 中`Meili.ApiKey`的值必须与容器中meili启动时设定的`MEILI_MASTER_KEY`环境变量值相同,默认为`paopao-meilisearch`. 可以在docker启动容器时通过`-e MEILI_MASTER_KEY=`设置该值。 + + +### 方式三. 使用 docker-compose 运行 +```sh +git clone https://github.com/rocboss/paopao-ce.git +cd paopao-ce && docker compose up -d +# visit http://localhost:8008 👀 paopao-ce +# visit http://localhost:8001 👀 RedisInsight +# visit http://localhost:8080 👀 phpMyAdmin +``` + +默认是使用config.yaml.sample的配置,如果需要自定义配置,请拷贝默认配置文件(比如config.yaml),修改后再同步配置到docker-compose.yaml如下: + +``` +# file: docker-compose.yaml +... + backend: + image: bitbus/paopao-ce:latest + restart: always + depends_on: + - db + - redis + - zinc + # modify below to reflect your custom configure + volumes: + - ./config.yaml:/app/paopao-ce/config.yaml + ports: + - 8008:8008 + networks: + - paopao-network +.... +``` + +> 注意:默认提供的 docker-compose.yaml 初衷是搭建本机开发调试环境,如果需要产品部署供外网访问,请自行调优配置参数或使用其他方式部署。 + +### 开发文档 +#### Docs文档说明 +`docs`目录提供了各种开发文档,包括: +* [deploy](docs/deploy/) - paopao-ce部署文档 +* [discuss](docs/discuss/) - 开发相关的问题交流论述文档 +* [openapi](docs/openapi/) - paopao-ce后端导出API文档 +* [proposal](docs/proposal/) - paopao-ce功能特性提按文档 +> 比如,关于paopao-ce的设计定位,可以参考[docs/proposal/001-关于paopao-ce的设计定位](docs/proposal/001-关于paopao-ce的设计定位.md),简要阐述了paopao-ce是如何定位自身的。 + +#### API文档 +开发者可以在本地开启`Docs`服务,浏览后端导出的API服务接口文档。 +* `config.yaml` 添加 `Docs` 功能项: +```yaml +... +Features: + Default: ["Base", "MySQL", "Option", "LocalOSS", "LoggerFile", "Docs"] + Docs: ["Docs:OpenAPI"] +... +``` + +* 构建时将 `docs` 添加到TAGS中: +```sh +make run TAGS='docs' + +# visit http://127.0.0.1:8011/docs/openapi +``` + +### 配置说明 + +`config.yaml.sample` 是一份完整的配置文件模版,paopao-ce启动时会读取`./custom/config.yaml`、`./config.yaml`任意一份配置文件(优先读取最先找到的文件)。 + +```sh +cp config.yaml.sample config.yaml +vim config.yaml # 修改参数 +paopao serve +``` + +配置文件中的 `Features` 小节是声明paopao-ce运行时开启哪些功能项: + +```yaml +... + +Features: + Default: ["Base", "MySQL", "Option", "LocalOSS", "LoggerFile"] + Develop: ["Base", "MySQL", "Option", "Sms", "AliOSS", "LoggerOtlp"] + Demo: ["Base", "MySQL", "Option", "Sms", "MinIO", "LoggerOtlp"] + Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile"] + Base: ["Zinc", "Redis", "Alipay",] + Option: ["SimpleCacheIndex"] + Sms: "SmsJuhe" + +... +``` + +如上: +Default/Develop/Demo/Slim 是不同 功能集套件(Features Suite), Base/Option 是子功能套件, Sms是关于短信验证码功能的参数选项。 + +这里 `Default`套件 代表的意思是: 使用`Base/Option` 中的功能,外加 `MySQL/LocalOSS/LoggerFile`功能,也就是说开启了`Zinc/Redis/Alipay/SimpleCacheIndex/MySQL/LocalOSS/LoggerFile` 7项功能; +`Develop`套件依例类推。 + +使用Feautures: + +```sh +release/paopao serve --help +Usage of release/paopao: + -features value + use special features + -no-default-features + whether use default features + +# 默认使用 Default 功能套件 +release/paopao serve + +# 不包含 default 中的功能集,仅仅使用 develop 中声明的功能集 +release/paopao serve --no-default-features --features develop + +# 使用 default 中的功能集,外加 sms 功能 +release/paopao serve --features sms + +# 手动指定需要开启的功能集 +release/paopao serve --no-default-features --features sqlite3,localoss,loggerfile,redis +``` + +目前支持的功能集合: +| 功能项 | 类别 | 状态 | 备注 | +| ----- | ----- | ----- | ----- | +|`Web` | 子服务 | 内测 | 开启Web服务| +|`Admin` | 子服务 | WIP | 开启Admin后台运维服务| +|`SpaceX` | 子服务 | WIP | 开启SpaceX服务| +|`Bot` | 子服务 | WIP | 开启Bot服务| +|`NativeOBS` | 子服务 | WIP | 开启NativeOBS服务| +|`Docs` | 子服务 | WIP | 开启开发者文档服务| +|`Frontend:Web` | 子服务 | 稳定 | 开启独立前端服务| +|`Frontend:EmbedWeb` | 子服务 | 稳定 | 开启内嵌于后端Web API服务中的前端服务| +|`Gorm` | 数据库 | 稳定(默认) | 使用[gorm](https://github.com/go-gorm/gorm)作为数据库的ORM,默认使用 `Gorm` + `MySQL`组合| +|`Sqlx`| 数据库 | WIP | 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据库的ORM| +|`Sqlc`| 数据库 | WIP | 使用[sqlc](https://github.com/kyleconroy/sqlc)自动生成ORM代码| +|`MySQL`| 数据库 | 稳定(默认) | 使用MySQL作为数据库| +|`Postgres`| 数据库 | 稳定 | 使用PostgreSQL作为数据库| +|`Sqlite3`| 数据库 | 稳定 | 使用Sqlite3作为数据库| +|`AliOSS` | 对象存储 | 稳定(推荐) |阿里云对象存储服务| +|`COS` | 对象存储 | 内测 |腾讯云对象存储服务| +|`HuaweiOBS` | 对象存储 | 内测 |华为云对象存储服务| +|`MinIO` | 对象存储 | 稳定 |[MinIO](https://github.com/minio/minio)对象存储服务| +|`S3` | 对象存储 | 内测 |AWS S3兼容的对象存储服务| +|`LocalOSS` | 对象存储 | 内测 |提供使用本地目录文件作为对象存储的功能,仅用于开发调试环境| +|`OSS:Retention` | 对象存储 | 内测 |基于对象存储系统的对象过期自动删除特性实现 先创建临时对象再持久化的功能| +|`OSS:TempDir` | 对象存储 | 内测 |基于对象存储系统的对象拷贝/移动特性实现 先创建临时对象再持久化的功能| +|`Redis` | 缓存 | 稳定 | Redis缓存功能 | +|`SimpleCacheIndex` | 缓存 | Deprecated | 提供简单的 广场推文列表 的缓存功能 | +|`BigCacheIndex` | 缓存 | Deprecated | 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 | +|`RedisCacheIndex` | 缓存 | Deprecated | 使用Redis缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 | +|`Zinc` | 搜索 | Deprecated | 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务 | +|`Meili` | 搜索 | 稳定(推荐) | 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务 | +|`Bleve` | 搜索 | WIP | 基于[Bleve](https://github.com/blevesearch/bleve)搜索引擎提供推文搜索服务 | +|[`Sentry`](docs/proposal/23040412-关于使用sentry用于错误追踪与性能检测的设计.md) | 监控 | 内测 | 使用Sentry进行错误跟踪与性能监控 | +|`LoggerFile` | 日志 | 稳定 | 使用文件写日志 | +|`LoggerZinc` | 日志 | Deprecated | 使用[Zinc](https://github.com/zinclabs/zinc)写日志 | +|`LoggerMeili` | 日志 | Deprecated | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 | +|`LoggerOpenObserve` | 日志 | Deprecated | 使用[OpenObserve](https://github.com/openobserve/openobserve)写日志 | +|`LoggerOtlp` | 日志 | 内测 | 使用[OpenTelemetry](https://github.com/open-telemetry/opentelemetry-go)写日志 | +|[`Friendship`](docs/proposal/22110410-关于Friendship功能项的设计.md) | 关系模式 | 内置 Builtin | 弱关系好友模式,类似微信朋友圈 | +|[`Followship`](docs/proposal/22110409-关于Followship功能项的设计.md) | 关系模式 | 内置 Builtin | 关注者模式,类似Twitter的Follow模式 | +|[`Lightship`](docs/proposal/22121409-关于Lightship功能项的设计.md) | 关系模式 | 弃用 Deprecated | 开放模式,所有推文都公开可见 | +|`Alipay` | 支付 | 稳定 | 开启基于[支付宝开放平台](https://open.alipay.com/)的钱包功能 | +|`Sms` | 短信验证 | 稳定 | 开启短信验证码功能,用于手机绑定验证手机是否注册者的;功能如果没有开启,手机绑定时任意短信验证码都可以绑定手机 | +|`Docs:OpenAPI` | 开发文档 | 稳定 | 开启openapi文档功能,提供web api文档说明(visit http://127.0.0.1:8008/docs/openapi) | +|[`Pyroscope`](docs/proposal/23021510-关于使用pyroscope用于性能调试的设计.md)| 性能优化 | 内测 | 开启Pyroscope功能用于性能调试 | +|[`Pprof`](docs/proposal/23062905-添加Pprof功能特性用于获取Profile.md)| 性能优化 | 内测 | 开启Pprof功能收集Profile信息 | +|`PhoneBind` | 其他 | 稳定 | 手机绑定功能 | +|`UseAuditHook` | 其他 | 内测 | 使用审核hook功能 | +|`DisableJobManager` | 其他 | 内测 | 禁止使用JobManager功能 | +|`Web:DisallowUserRegister` | 功能特性 | 稳定 | 不允许用户注册 | + +> 功能项状态详情参考 [features-status](features-status.md). + +### 搭建依赖环境 +#### [Zinc](https://github.com/zinclabs/zinc) 搜索引擎: +* Zinc运行 +```sh +# 创建用于存放zinc数据的目录 +mkdir -p data/zinc/data + +# 使用Docker运行zinc +docker run -d --name zinc --user root -v ${PWD}/data/zinc/data:/data -p 4080:4080 -e ZINC_FIRST_ADMIN_USER=admin -e ZINC_FIRST_ADMIN_PASSWORD=admin -e DATA_PATH=/data public.ecr.aws/zinclabs/zinc:latest + +# 查看zinc运行状态 +docker ps +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +41465feea2ff getmeili/meilisearch:v0.27.0 "tini -- /bin/sh -c …" 20 hours ago Up 20 hours 0.0.0.0:7700->7700/tcp paopao-ce-meili-1 +7daf982ca062 public.ecr.aws/prabhat/zinc:latest "/go/bin/zinc" 3 weeks ago Up 6 days 0.0.0.0:4080->4080/tcp zinc + +# 使用docker compose运行 +docker compose up -d zinc +# visit http://localhost:4080 打开自带的ui管理界面 +``` + +* 修改Zinc配置 +```yaml +# features中加上 Zinc 和 LoggerZinc +Features: + Default: ["Zinc", "LoggerZinc", "Base", "Sqlite3", "BigCacheIndex","MinIO"] +... +LoggerZinc: # 使用Zinc写日志 + Host: 127.0.0.1:4080 # 这里的host就是paopao-ce能访问到的zinc主机 + Index: paopao-log + User: admin + Password: admin + Secure: False # 如果使用https访问zinc就设置为True +... +Zinc: # Zinc搜索配置 + Host: 127.0.0.1:4080 + Index: paopao-data + User: admin + Password: admin + Secure: False +``` + +#### [Meilisearch](https://github.com/meilisearch/meilisearch) 搜索引擎: +* Meili运行 +```sh +mkdir -p data/meili/data + +# 使用Docker运行 +docker run -d --name meili -v ${PWD}/data/meili/data:/meili_data -p 7700:7700 -e MEILI_MASTER_KEY=paopao-meilisearch getmeili/meilisearch:v0.29.0 +# visit http://localhost:7700 打开自带的搜索前端ui + +# 使用docker compose运行,需要删除docker-compose.yaml中关于meili的注释 +docker compose up -d meili + +# 查看meili运行状态 +docker compose ps +NAME COMMAND SERVICE STATUS PORTS +paopao-ce-meili-1 "tini -- /bin/sh -c …" meili running 0.0.0.0:7700->7700/tcp +``` + +* 修改Meili配置 +```yaml +# features中加上 Meili 和 LoggerMeili +Features: + Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex","MinIO"] +... +LoggerMeili: # 使用Meili写日志 + Host: 127.0.0.1:7700 + Index: paopao-log + ApiKey: paopao-meilisearch + Secure: False + MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5 + MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100 +... +Meili: # Meili搜索配置 + Host: 127.0.0.1:7700 # 这里的host就是paopao-ce能访问到的meili主机 + Index: paopao-data + ApiKey: paopao-meilisearch + Secure: False # 如果使用https访问meili就设置为True +``` + +#### [MinIO](https://github.com/minio/minio) 对象存储服务 +* MinIO运行 +```sh +mkdir -p data/minio/data + +# 使用Docker运行 +docker run -d --name minio -v ${PWD}/data/minio/data:/data -p 9000:9000 -p 9001:9001 -e MINIO_ROOT_USER=minio-root-user -e MINIO_ROOT_PASSWORD=minio-root-password -e MINIO_DEFAULT_BUCKETS=paopao:public bitnami/minio:latest + +# 使用docker compose运行, 需要删除docker-compose.yaml中关于minio的注释 +docker compose up -d minio +``` + +* 修改Minio配置 +```yaml +# features中加上 MinIO +Features: + Default: ["MinIO", "Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex"] +... +MinIO: # MinIO 存储配置 + AccessKey: Q3AM3UQ867SPQQA43P2F # AccessKey/SecretKey 需要登入minio管理界面手动创建,管理界面地址: http://127.0.0.1:9001 + SecretKey: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG + Secure: False + Endpoint: 127.0.0.1:9000 # 根据部署的minio主机修改对应地址 + Bucket: paopao # 如上,需要在管理界面创建bucket并赋予外部可读写权限 + Domain: 127.0.0.1:9000 # minio外网访问的地址(如果想让外网访问,这里需要设置为外网可访问到的minio主机地址) +... +``` + +#### [OpenObserve](https://github.com/openobserve/openobserve) 日志收集、指标度量、轨迹跟踪 +* OpenObserve运行 +```sh +# 使用Docker运行 +mkdir data && docker run -v $PWD/data:/data -e ZO_DATA_DIR="/data" -p 5080:5080 \ + -e ZO_ROOT_USER_EMAIL="root@paopao.info" -e ZO_ROOT_USER_PASSWORD="paopao-ce" \ + public.ecr.aws/zinclabs/openobserve:latest + +# 使用docker compose运行, 需要删除docker-compose.yaml中关于openobserve的注释 +docker compose up -d openobserve +# visit http://loclahost:5080 +``` + +* 修改LoggerOpenObserve配置 +```yaml +# features中加上 LoggerOpenObserve +Features: + Default: ["Meili", "LoggerOpenObserve", "Base", "Sqlite3", "BigCacheIndex"] +... +LoggerOpenObserve: # 使用OpenObserve写日志 + Host: 127.0.0.1:5080 + Organization: paopao-ce + Stream: default + User: root@paopao.info + Password: tiFEI8UeJWuYA7kN + Secure: False +... +``` + +#### [Pyroscope](https://github.com/pyroscope-io/pyroscope) 性能剖析 +* Pyroscope运行 +```sh +mkdir -p data/minio/data + +# 使用Docker运行 +docker run -it -p 4040:4040 pyroscope/pyroscope:latest server +# 使用docker compose运行, 需要删除docker-compose.yaml中关于pyroscope的注释 +docker compose up -d pyroscope +# visit http://loclahost:4040 +``` + +* 修改Pyroscope配置 +```yaml +# features中加上 Pyroscope +Features: + Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "Pyroscope"] +... +Pyroscope: # Pyroscope配置 + AppName: "paopao-ce" + Endpoint: "http://localhost:4040" # Pyroscope server address + AuthToken: # Pyroscope authentication token + Logger: none # Pyroscope logger (standard | logrus | none) +... +``` + +### 源代码分支管理 +**主代码库`github.com/rocboss/paopao-ce`** +```bash +git branch +main +beta +dev +feature/bleve +feature/followship +feature/mir +feature/localoss +jc/alimy +r/paopao-plus +r/paopao-pro +x/sqlc +x/sqlx +``` +**分支说明** +| 名称 | 说明 | 备注| +| ----- | ----- | ----- | +| [`main`](https://github.com/rocboss/paopao-ce) | 主分支 |分支`main`是主分支,也是paopao-ce的稳定版本发布分支,只有经过内部测试,没有重大bug出现的稳定代码才会推进到这个分支;该分支主要由`beta`分支代码演进而来,原则上**只接受bug修复PR**。`rc版本/稳定版本` 发布都应该在`main`主分支中进行。| +| [`beta`](https://github.com/rocboss/paopao-ce/tree/beta) | 公测分支 |分支`beta`是公测分支,代码推进到`main`主分支的候选分支;该分支主要由`alpha`分支代码演进而来,**接受bug修复以及新功能优化的PR**,原则上不接受新功能PR。`beta版本` 发布都应该在`beta`公测分支下进行。| +| [`alpha`](https://github.com/rocboss/paopao-ce/tree/alpha) | 内测分支 |分支`alpha`是内测分支,代码推进到`beta`分支的候选分支;该分支主要由`dev`分支代码演进而来,**接受bug修复以及新功能相关的PR**,接受新功能PR。分支代码演进到一个里程碑式的阶段后**冻结所有新功能**,合并代码到`beta`公测分支进行下一阶段的持续演进。`alpha版本` 发布都应该在`alpha`内测分支下进行。| +| [`dev`](https://github.com/rocboss/paopao-ce/tree/dev) | 开发分支 | 分支`dev`是开发分支,**不定期频繁更新**,接受 *新功能PR、代码优化PR、bug修复PR*;**新功能PR** 都应该首先提交给`dev`分支进行合并,bug修复/新功能开发/代码优化 **阶段性冻结** 后将代码演进合并到`alpha`分支。| +| `feature/*` | 子功能分支 |`feature/*`是新功能子分支,一般新功能子分支都是 *从`dev`开发分支fork出来的*;子功能分支 **只专注于该新功能** 代码的开发/优化,待开发接近内测阶段 *提交新功能PR给`dev`分支进行review/merge*,待新功能代码演进到`beta`分支后,原则上是可以删除该分支,但也可以保留到稳定版本发布。**该分支专注于新功能的开发,只接受新功能的bug修复/优化PR**。| +| `jc/*` |维护者的开发分支|`jc/*`是代码库维护者的开发分支,一般包含一些局部优化或者bug修复代码,有时可以直接将代码merge到`dev/beta`分支,原则上不允许直接merge代码到`main`主分支。| +| `x/*` |实验分支|`x/*`是技术实验分支,某些技术的引入需要经过具体的代码实现与真实场景的测评,考量评估后如果某项技术适合引入到paopao-ce,就fork出一个`feature/*`分支,作为新功能引入到paopao-ce。一般一些比较激进的技术,从`dev`分支fork出一个新的`x/*`分支,各种尝试、考量、评估后,或丢弃、或引入到paopao-ce。| +| `t/*` | 临时分支 |`t/*`是临时发版本分支,一般 `beta` 分支演进到正式版本发布前的最后某个beta版本(比如v0.2.0-beta)就从beta分支fork出一个 `t/*` 分支用于向 `main` 分支提交 PR 用于Review,待 PR Reviewed 合并到 `main` 分支后,可以删除这个临时创建的分支。这样设计主要是考虑到有时合并到 `main` 分支时,需要Review的时间可能会长一些,而dev分支的代码又急需推进到beta分支以发布下一个alpha版本用于内测,相当于为下一个测试版本发布腾地方。| +| `r/*` |发行版本分支|`r/*`是不同发行版本分支,不同发行版本各有不同的侧重点,可以根据需要选择适合的发行版本。| + +**发行版本分支说明** +| 名称 | 说明 | 维护者 | 备注 | +| ----- | ----- | ----- | ----- | +|[`paopao-ce`](https://github.com/rocboss/paopao-ce/tree/dev)|paopao-ce 主发行版本|[ROC](https://github.com/rocboss 'ROC')|该分支 [数据逻辑层](https://github.com/rocboss/paopao-ce/tree/dev/internal/dao/jinzhu) 使用[gorm](https://github.com/go-gorm/gorm)作为数据逻辑层的ORM框架,适配MySQL/PostgreSQL/Sqlite3数据库。| +|[`r/paopao-ce`](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce)|paopao-ce 主分支预览版本|[ROC](https://github.com/rocboss 'ROC')
[北野](https://github.com/alimy 'Michael Li')|该分支 [数据逻辑层](https://github.com/rocboss/paopao-ce/tree/dev/internal/dao/jinzhu) 使用[gorm](https://github.com/go-gorm/gorm)作为数据逻辑层的ORM框架,适配MySQL/PostgreSQL/Sqlite3数据库。代码较`main`分支新,是主发行版本的前瞻预览版本。| +|[`r/paopao-ce-plus`](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-plus)|paopao-ce-plus 发行版本|[北野](https://github.com/alimy 'Michael Li')|该分支 [数据逻辑层](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-plus/internal/dao/sakila) 使用[sqlx](https://github.com/jmoiron/sqlx)作为数据逻辑层的ORM框架,专注于为MySQL/PostgreSQL/Sqlite3使用更优化的查询语句以提升数据检索效率。建议熟悉[sqlx](https://github.com/jmoiron/sqlx)的开发人员可以基于此版本来做 二次开发。| +|[`r/paopao-ce-pro`](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-pro)|paopao-ce-pro 发行版本|[北野](https://github.com/alimy 'Michael Li')|该分支 [数据逻辑层](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-pro/internal/dao/slonik) 使用[sqlc](https://github.com/kyleconroy/sqlc)作为sql语句生成器自动生成ORM代码,专门针对特定数据库MySQL/PostgreSQL进行查询优化,熟悉[sqlc](https://github.com/kyleconroy/sqlc)的开发人员可以基于此版本来做 二次开发。(另:分支目前只使用[pgx-v5](https://github.com/jackc/pgx)适配了PostgreSQL数据库,后续或许会适配MySQL/TiDB数据库。)| +|[`r/paopao-ce-xtra`](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-xtra)|paopao-ce-xtra 发行版本|[北野](https://github.com/alimy 'Michael Li')|该分支 是r/paopao-ce、r/paopao-ce-plus、r/paopao-ce-pro的合集| +|[`r/paopao-ce-mini`](https://github.com/rocboss/paopao-ce/tree/r/paopao-ce-mini)|paopao-ce-mini 发行版本|[北野](https://github.com/alimy 'Michael Li')|该分支是paopao-ce最小可用版本,专注于个人部署、一键傻瓜式最简部署| + +**代码分支演进图** +![](docs/proposal/.assets/000-01.png) + +### 部署站点信息 +* [官方 paopao.info](https://www.paopao.info) +> 具体部署站点信息请查阅 [deployed-sites](./deployed-sites.md 'deployed sites'). 欢迎站长将已部署PaoPao实例的站点信息添加到 [deployed-sites](./deployed-sites.md 'deployed sites') 列表中。 + +#### Collaborator's paopao account +| 昵称 | [@GitHub](https://github.com 'github.com') | [@PaoPao](https://www.paopao.info 'paopao.info') | +| ----- | ----- | ----- | +| ROC | [ROC](https://github.com/rocboss 'ROC')|[ROC](https://www.paopao.info/#/user?username=roc 'ROC @roc')| +| [北野](https://alimy.me '糊涂小栈') | [Michael Li](https://github.com/alimy 'Michael Li') | [alimy](https://www.paopao.info/#/user?username=alimy '北野 @alimy')| +| orzi!| [orzi!](https://github.com/orziz 'orzi!')|| + +### 其他说明 + +建议后端服务使用 `supervisor` 守护进程,并通过 `nginx` 反向代理后,提供API给前端服务调用。 + +短信通道使用的[聚合数据](https://www.juhe.cn/),如果申请不下来,可以考虑替换其他服务商。 + +代码结构比较简单,很方便扩展,开发文档请参阅[docs](docs '开发文档'). + + +[contributors-shield]: https://img.shields.io/github/contributors/rocboss/paopao-ce?style=flat +[contributors-url]: https://github.com/rocboss/paopao-ce/graphs/contributors +[goreport-shield]: https://goreportcard.com/badge/github.com/rocboss/paopao-ce +[goreport-url]: https://goreportcard.com/report/github.com/rocboss/paopao-ce +[forks-shield]: https://img.shields.io/github/forks/rocboss/paopao-ce?style=flat +[forks-url]: https://github.com/rocboss/paopao-ce/network/members +[stars-shield]: https://img.shields.io/github/stars/rocboss/paopao-ce.svg?style=flat +[stars-url]: https://github.com/rocboss/paopao-ce/stargazers +[issues-shield]: https://img.shields.io/github/issues/rocboss/paopao-ce.svg?style=flat +[issues-url]: https://github.com/rocboss/paopao-ce/issues +[license-shield]: https://img.shields.io/github/license/rocboss/paopao-ce.svg?style=flat +[license-url]: https://github.com/rocboss/paopao-ce/blob/master/LICENSE.txt +[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=flat&logo=linkedin&colorB=555 +[product-light-screenshot]: https://cdn.rocs.me/static/paopao-light.jpeg +[product-dark-screenshot]: https://cdn.rocs.me/static/paopao-dark.jpeg diff --git a/README.md b/README.md index 11026ba6..c20e6cf2 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,9 @@ PaoPao主要由以下优秀的开源项目/工具构建 * [Go](https://go.dev/ 'go') * [Gin](https://gin-gonic.com/ 'gin') * [Mir](https://github.com/alimy/mir 'go-mir') -* [Buf](https://github.com/bufbuild/buf 'buf') -* [gRPC](https://github.com/grpc/grpc-go 'grpc-go') * [Meilisearch](https://www.meilisearch.com/ 'meilisearch') +* [OpenTelemetry](https://github.com/open-telemetry/opentelemetry-go 'OpenTelemetry') +* [OpenObserve](https://github.com/openobserve/openobserve 'OpenObserve') #### 前端: * [Naive UI](https://www.naiveui.com/) @@ -65,7 +65,7 @@ PaoPao主要由以下优秀的开源项目/工具构建 ### 环境要求 -* Go (1.20+) +* Go (1.22+) * Node.js (14+) * MySQL (5.7+) * Redis @@ -74,227 +74,15 @@ PaoPao主要由以下优秀的开源项目/工具构建 以上环境版本为PaoPao官方的开发版本,仅供参考,其他版本的环境未进行充分测试 ### 安装说明 - - -### 方式一. 手动安装(推荐) - -克隆代码库 - - ```sh - git clone https://github.com/rocboss/paopao-ce.git - ``` - -#### 后端 - -1. 导入项目根目录下的 `scripts/paopao.sql` 文件至MySQL数据库 -2. 拷贝项目根目录下 `config.yaml.sample` 文件至 `config.yaml`,按照注释完成配置编辑 -3. 编译后端 - 编译api服务: - ```sh - make build - ``` - 编译api服务、内嵌web前端ui: - ```sh - make build - ``` - 也可以使用精简模式编译,不内嵌web前端ui: - ```sh - make build TAGS='slim embed' - ``` - 编译后在`release`目录可以找到对应可执行文件。 - ```sh - release/paopao - ``` - -4. 直接运行后端 - 运行api服务: - ```sh - make run - ``` - 运行api服务、web前端ui服务: - ```sh - make run TAGS='embed' - ``` - 提示: 如果需要内嵌web前端ui,请先构建web前端(建议设置web/.env为VITE_HOST="")。 - -5. 使用内置的Migrate机制自动升级维护SQL DDL: - ```sh - # 添加 Migration 功能到 Features 中 开启migrate功能 - vim config.yaml - # file: config.yaml - # Features: - # Default: ["Base", "MySQL", "Zinc", "MinIO", "LoggerZinc", "Migration"] - - # 编译时加入migration tag编译出支持migrate功能的可执行文件 - make build TAGS='migration' - release/paopao - - # 或者 带上migration tag直接运行 - make run TAGS='migration' - ``` - > 注意:默认编译出来的可执行文件是不内置migrate功能,需要编译时带上migration tag才能内置支持migrage功能。 - - -#### 前端 - -1. 进入前端目录 `web`,拷贝`.env` 到 `.env.local`,编辑 `.env.local ` 文件中后端服务地址及其他配置项,下载依赖包 - - ```sh - cd ./web && cp .env .env.local - vim .env.local - yarn - ``` - -2. 编译前端 - - ```sh - yarn build - ``` - - build完成后,可以在dist目录获取编译产出,配置nginx指向至该目录即可 - -#### 桌面端 - -1. 进入前端目录 `web`,拷贝`.env` 到 `.env.local`,编辑 `.env.local ` 文件中后端服务地址及其他配置项,下载依赖包 - - ```sh - cd ./web && cp .env .env.local - vim .env.local - yarn - ``` - -2. 编译前端 - - ```sh - yarn build - ``` - -3. 构建桌面端 - ```sh - yarn tauri build - ``` - 桌面端是使用[Rust](https://www.rust-lang.org/) + [tauri](https://github.com/tauri-apps/tauri)编写 - 的,需要安装tauri的依赖,具体参考[https://tauri.studio/v1/guides/getting-started/prerequisites](https://tauri.studio/v1/guides/getting-started/prerequisites). - - -### 方式二. 使用Docker构建、运行 - * 后端: - ```sh - # 默认参数构建, 默认内嵌web ui并设置api host为空 - docker build -t your/paopao-ce:tag . - - # 内嵌web ui并且自定义API host参数 - docker build -t your/paopao-ce:tag --build-arg API_HOST=http://api.paopao.info . - - # 内嵌web ui并且使用本地web/.env中的API host - docker build -t your/paopao-ce:tag --build-arg USE_API_HOST=no . - - # 内嵌web ui并且使用本地编译的web/dist构建 - docker build -t your/paopao-ce:tag --build-arg USE_DIST=yes . - - # 只编译api server - docker build -t your/paopao-ce:tag --build-arg EMBED_UI=no . - - # 运行 - mkdir custom && docker run -d -p 8008:8008 -v ${PWD}/custom:/app/paopao-ce/custom -v ${PWD}/config.yaml.sample:/app/paopao-ce/config.yaml your/paopao-ce:tag - - # 或者直接运行构建好的docker image - mkdir custom && docker run -d -p 8008:8008 -v ${PWD}/custom:/app/paopao-ce/custom -v ${PWD}/config.yaml.sample:/app/paopao-ce/config.yaml bitbus/paopao-ce:latest - ``` - - * 前端: - ```sh - cd web - - # 默认参数构建 - docker build -t your/paopao-ce:web . - - # 自定义API host 参数构建 - docker build -t your/paopao-ce:web --build-arg API_HOST=http://api.paopao.info . - - # 使用本地编译的dist构建 - docker build -t your/paopao-ce:web --build-arg USE_DIST=yes . - - # 运行 - docker run -d -p 8010:80 your/paopao-ce:web - ``` - - * All-In-One: - ```sh - # 构建Image - docker buildx build --build-arg USE_DIST="yes" -t your/paopao-ce:all-in-one-latest -f Dockerfile.allinone . - - # 运行 - docker run --name paopao-ce-allinone -d -p 8000:8008 -p 7700:7700 -v ./data/custom:/app/custom -v ./data/meili_data:/app/meili_data your/paopao-ce:all-in-one-latest - - # 或者使用官方Image运行 - docker run --name paopao-ce-allinone -d -p 8000:8008 -p 7700:7700 -v ./data/custom:/app/custom -v ./data/meili_data:/app/meili_data bitbus/paopao-ce:all-in-one-latest - - # 或者使用官方Image运行 + 自定义config.yaml - docker run --name paopao-ce-allinone -d -p 8000:8008 -p 7700:7700 -v ./config.yaml:/app/config.yaml -v ./data/custom:/app/custom -v ./data/meili_data:/app/meili_data bitbus/paopao-ce:all-in-one-latest - ``` - > 注意在`config.yaml` 中`Meili.ApiKey`的值必须与容器中meili启动时设定的`MEILI_MASTER_KEY`环境变量值相同,默认为`paopao-meilisearch`. 可以在docker启动容器时通过`-e MEILI_MASTER_KEY=`设置该值。 - - -### 方式三. 使用 docker-compose 运行 -```sh -git clone https://github.com/rocboss/paopao-ce.git -cd paopao-ce && docker compose up -d -# visit http://localhost:8008 👀 paopao-ce -# visit http://localhost:8001 👀 RedisInsight -# visit http://localhost:8080 👀 phpMyAdmin -``` - -默认是使用config.yaml.sample的配置,如果需要自定义配置,请拷贝默认配置文件(比如config.yaml),修改后再同步配置到docker-compose.yaml如下: - -``` -# file: docker-compose.yaml -... - backend: - image: bitbus/paopao-ce:latest - restart: always - depends_on: - - db - - redis - - zinc - # modify below to reflect your custom configure - volumes: - - ./config.yaml:/app/paopao-ce/config.yaml - ports: - - 8008:8008 - networks: - - paopao-network -.... -``` - -> 注意:默认提供的 docker-compose.yaml 初衷是搭建本机开发调试环境,如果需要产品部署供外网访问,请自行调优配置参数或使用其他方式部署。 +参考 [安装说明 (INSTALL.md);](INSTALL.md '参考 安装说明') ### 开发文档 #### Docs文档说明 `docs`目录提供了各种开发文档,包括: * [deploy](docs/deploy/) - paopao-ce部署文档 -* [discuss](docs/discuss/) - 开发相关的问题交流论述文档 * [openapi](docs/openapi/) - paopao-ce后端导出API文档 * [proposal](docs/proposal/) - paopao-ce功能特性提按文档 -> 比如,关于paopao-ce的设计定位,可以参考[docs/proposal/001-关于paopao-ce的设计定位](docs/proposal/001-关于paopao-ce的设计定位.md),简要阐述了paopao-ce是如何定位自身的。 - -#### API文档 -开发者可以在本地开启`Docs`服务,浏览后端导出的API服务接口文档。 -* `config.yaml` 添加 `Docs` 功能项: -```yaml -... -Features: - Default: ["Base", "MySQL", "Option", "LocalOSS", "LoggerFile", "Docs"] - Docs: ["Docs:OpenAPI"] -... -``` - -* 构建时将 `docs` 添加到TAGS中: -```sh -make run TAGS='docs' - -# visit http://127.0.0.1:8011/docs/openapi -``` +> 比如,关于paopao-ce的设计定位,可以参考[docs/proposal/001-关于paopao-ce的设计定位](docs/proposal/22110411-关于paopao-ce的设计定位.md),简要阐述了paopao-ce是如何定位自身的。 ### 配置说明 @@ -313,8 +101,8 @@ paopao serve Features: Default: ["Base", "MySQL", "Option", "LocalOSS", "LoggerFile"] - Develop: ["Base", "MySQL", "Option", "Sms", "AliOSS", "LoggerZinc"] - Demo: ["Base", "MySQL", "Option", "Sms", "MinIO", "LoggerZinc"] + Develop: ["Base", "MySQL", "Option", "Sms", "AliOSS", "LoggerOtlp"] + Demo: ["Base", "MySQL", "Option", "Sms", "MinIO", "LoggerOtlp"] Slim: ["Base", "Sqlite3", "LocalOSS", "LoggerFile"] Base: ["Zinc", "Redis", "Alipay",] Option: ["SimpleCacheIndex"] @@ -381,14 +169,15 @@ release/paopao serve --no-default-features --features sqlite3,localoss,loggerfil |`SimpleCacheIndex` | 缓存 | Deprecated | 提供简单的 广场推文列表 的缓存功能 | |`BigCacheIndex` | 缓存 | Deprecated | 使用[BigCache](https://github.com/allegro/bigcache)缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 | |`RedisCacheIndex` | 缓存 | Deprecated | 使用Redis缓存 广场推文列表,缓存每个用户每一页,简单做到千人千面 | -|`Zinc` | 搜索 | 稳定(推荐) | 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务 | +|`Zinc` | 搜索 | Deprecated | 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务 | |`Meili` | 搜索 | 稳定(推荐) | 基于[Meilisearch](https://github.com/meilisearch/meilisearch)搜索引擎提供推文搜索服务 | |`Bleve` | 搜索 | WIP | 基于[Bleve](https://github.com/blevesearch/bleve)搜索引擎提供推文搜索服务 | |[`Sentry`](docs/proposal/23040412-关于使用sentry用于错误追踪与性能检测的设计.md) | 监控 | 内测 | 使用Sentry进行错误跟踪与性能监控 | |`LoggerFile` | 日志 | 稳定 | 使用文件写日志 | -|`LoggerZinc` | 日志 | 稳定(推荐) | 使用[Zinc](https://github.com/zinclabs/zinc)写日志 | -|`LoggerMeili` | 日志 | 内测 | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 | -|`LoggerOpenObserve` | 日志 | 内测 | 使用[OpenObserve](https://github.com/openobserve/openobserve)写日志 | +|`LoggerZinc` | 日志 | Deprecated | 使用[Zinc](https://github.com/zinclabs/zinc)写日志 | +|`LoggerMeili` | 日志 | Deprecated | 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志 | +|`LoggerOpenObserve` | 日志 | Deprecated | 使用[OpenObserve](https://github.com/openobserve/openobserve)写日志 | +|`LoggerOtlp` | 日志 | 内测 | 使用[OpenTelemetry](https://github.com/open-telemetry/opentelemetry-go)写日志 | |[`Friendship`](docs/proposal/22110410-关于Friendship功能项的设计.md) | 关系模式 | 内置 Builtin | 弱关系好友模式,类似微信朋友圈 | |[`Followship`](docs/proposal/22110409-关于Followship功能项的设计.md) | 关系模式 | 内置 Builtin | 关注者模式,类似Twitter的Follow模式 | |[`Lightship`](docs/proposal/22121409-关于Lightship功能项的设计.md) | 关系模式 | 弃用 Deprecated | 开放模式,所有推文都公开可见 | @@ -403,170 +192,6 @@ release/paopao serve --no-default-features --features sqlite3,localoss,loggerfil |`Web:DisallowUserRegister` | 功能特性 | 稳定 | 不允许用户注册 | > 功能项状态详情参考 [features-status](features-status.md). - -### 搭建依赖环境 -#### [Zinc](https://github.com/zinclabs/zinc) 搜索引擎: -* Zinc运行 -```sh -# 创建用于存放zinc数据的目录 -mkdir -p data/zinc/data - -# 使用Docker运行zinc -docker run -d --name zinc --user root -v ${PWD}/data/zinc/data:/data -p 4080:4080 -e ZINC_FIRST_ADMIN_USER=admin -e ZINC_FIRST_ADMIN_PASSWORD=admin -e DATA_PATH=/data public.ecr.aws/zinclabs/zinc:latest - -# 查看zinc运行状态 -docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -41465feea2ff getmeili/meilisearch:v0.27.0 "tini -- /bin/sh -c …" 20 hours ago Up 20 hours 0.0.0.0:7700->7700/tcp paopao-ce-meili-1 -7daf982ca062 public.ecr.aws/prabhat/zinc:latest "/go/bin/zinc" 3 weeks ago Up 6 days 0.0.0.0:4080->4080/tcp zinc - -# 使用docker compose运行 -docker compose up -d zinc -# visit http://localhost:4080 打开自带的ui管理界面 -``` - -* 修改Zinc配置 -```yaml -# features中加上 Zinc 和 LoggerZinc -Features: - Default: ["Zinc", "LoggerZinc", "Base", "Sqlite3", "BigCacheIndex","MinIO"] -... -LoggerZinc: # 使用Zinc写日志 - Host: 127.0.0.1:4080 # 这里的host就是paopao-ce能访问到的zinc主机 - Index: paopao-log - User: admin - Password: admin - Secure: False # 如果使用https访问zinc就设置为True -... -Zinc: # Zinc搜索配置 - Host: 127.0.0.1:4080 - Index: paopao-data - User: admin - Password: admin - Secure: False -``` - -#### [Meilisearch](https://github.com/meilisearch/meilisearch) 搜索引擎: -* Meili运行 -```sh -mkdir -p data/meili/data - -# 使用Docker运行 -docker run -d --name meili -v ${PWD}/data/meili/data:/meili_data -p 7700:7700 -e MEILI_MASTER_KEY=paopao-meilisearch getmeili/meilisearch:v0.29.0 -# visit http://localhost:7700 打开自带的搜索前端ui - -# 使用docker compose运行,需要删除docker-compose.yaml中关于meili的注释 -docker compose up -d meili - -# 查看meili运行状态 -docker compose ps -NAME COMMAND SERVICE STATUS PORTS -paopao-ce-meili-1 "tini -- /bin/sh -c …" meili running 0.0.0.0:7700->7700/tcp -``` - -* 修改Meili配置 -```yaml -# features中加上 Meili 和 LoggerMeili -Features: - Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex","MinIO"] -... -LoggerMeili: # 使用Meili写日志 - Host: 127.0.0.1:7700 - Index: paopao-log - ApiKey: paopao-meilisearch - Secure: False - MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5 - MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100 -... -Meili: # Meili搜索配置 - Host: 127.0.0.1:7700 # 这里的host就是paopao-ce能访问到的meili主机 - Index: paopao-data - ApiKey: paopao-meilisearch - Secure: False # 如果使用https访问meili就设置为True -``` - -#### [MinIO](https://github.com/minio/minio) 对象存储服务 -* MinIO运行 -```sh -mkdir -p data/minio/data - -# 使用Docker运行 -docker run -d --name minio -v ${PWD}/data/minio/data:/data -p 9000:9000 -p 9001:9001 -e MINIO_ROOT_USER=minio-root-user -e MINIO_ROOT_PASSWORD=minio-root-password -e MINIO_DEFAULT_BUCKETS=paopao:public bitnami/minio:latest - -# 使用docker compose运行, 需要删除docker-compose.yaml中关于minio的注释 -docker compose up -d minio -``` - -* 修改Minio配置 -```yaml -# features中加上 MinIO -Features: - Default: ["MinIO", "Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex"] -... -MinIO: # MinIO 存储配置 - AccessKey: Q3AM3UQ867SPQQA43P2F # AccessKey/SecretKey 需要登入minio管理界面手动创建,管理界面地址: http://127.0.0.1:9001 - SecretKey: zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG - Secure: False - Endpoint: 127.0.0.1:9000 # 根据部署的minio主机修改对应地址 - Bucket: paopao # 如上,需要在管理界面创建bucket并赋予外部可读写权限 - Domain: 127.0.0.1:9000 # minio外网访问的地址(如果想让外网访问,这里需要设置为外网可访问到的minio主机地址) -... -``` - -#### [OpenObserve](https://github.com/openobserve/openobserve) 日志收集、指标度量、轨迹跟踪 -* OpenObserve运行 -```sh -# 使用Docker运行 -mkdir data && docker run -v $PWD/data:/data -e ZO_DATA_DIR="/data" -p 5080:5080 \ - -e ZO_ROOT_USER_EMAIL="root@paopao.info" -e ZO_ROOT_USER_PASSWORD="paopao-ce" \ - public.ecr.aws/zinclabs/openobserve:latest - -# 使用docker compose运行, 需要删除docker-compose.yaml中关于openobserve的注释 -docker compose up -d openobserve -# visit http://loclahost:5080 -``` - -* 修改LoggerOpenObserve配置 -```yaml -# features中加上 LoggerOpenObserve -Features: - Default: ["Meili", "LoggerOpenObserve", "Base", "Sqlite3", "BigCacheIndex"] -... -LoggerOpenObserve: # 使用OpenObserve写日志 - Host: 127.0.0.1:5080 - Organization: paopao-ce - Stream: default - User: root@paopao.info - Password: tiFEI8UeJWuYA7kN - Secure: False -... -``` - -#### [Pyroscope](https://github.com/pyroscope-io/pyroscope) 性能剖析 -* Pyroscope运行 -```sh -mkdir -p data/minio/data - -# 使用Docker运行 -docker run -it -p 4040:4040 pyroscope/pyroscope:latest server -# 使用docker compose运行, 需要删除docker-compose.yaml中关于pyroscope的注释 -docker compose up -d pyroscope -# visit http://loclahost:4040 -``` - -* 修改Pyroscope配置 -```yaml -# features中加上 Pyroscope -Features: - Default: ["Meili", "LoggerMeili", "Base", "Sqlite3", "BigCacheIndex", "Pyroscope"] -... -Pyroscope: # Pyroscope配置 - AppName: "paopao-ce" - Endpoint: "http://localhost:4040" # Pyroscope server address - AuthToken: # Pyroscope authentication token - Logger: none # Pyroscope logger (standard | logrus | none) -... -``` ### 源代码分支管理 **主代码库`github.com/rocboss/paopao-ce`** @@ -575,10 +200,7 @@ git branch main beta dev -feature/bleve feature/followship -feature/mir -feature/localoss jc/alimy r/paopao-plus r/paopao-pro @@ -615,21 +237,6 @@ x/sqlx * [官方 paopao.info](https://www.paopao.info) > 具体部署站点信息请查阅 [deployed-sites](./deployed-sites.md 'deployed sites'). 欢迎站长将已部署PaoPao实例的站点信息添加到 [deployed-sites](./deployed-sites.md 'deployed sites') 列表中。 -#### Collaborator's paopao account -| 昵称 | [@GitHub](https://github.com 'github.com') | [@PaoPao](https://www.paopao.info 'paopao.info') | -| ----- | ----- | ----- | -| ROC | [ROC](https://github.com/rocboss 'ROC')|[ROC](https://www.paopao.info/#/user?username=roc 'ROC @roc')| -| [北野](https://alimy.me '糊涂小栈') | [Michael Li](https://github.com/alimy 'Michael Li') | [alimy](https://www.paopao.info/#/user?username=alimy '北野 @alimy')| -| orzi!| [orzi!](https://github.com/orziz 'orzi!')|| - -### 其他说明 - -建议后端服务使用 `supervisor` 守护进程,并通过 `nginx` 反向代理后,提供API给前端服务调用。 - -短信通道使用的[聚合数据](https://www.juhe.cn/),如果申请不下来,可以考虑替换其他服务商。 - -代码结构比较简单,很方便扩展,开发文档请参阅[docs](docs '开发文档'). - ## 👯‍♀️ 贡献 paopao-ce 是一个利用 *业余时间* 本着 **"Just for fun just do it."** 的心态 *持续有序* **开发/优化/维护**的开源项目,没有KPI考核、没有Roadmap进度压力、没有技术支持日程安排,或许有些许不足之处,但是重在精神可嘉。 借用网络中的话 **"F\*k talk, f\*k of tech innovation, Shut up and show me your code."** 一切都因更好的体验,一切都是为了爱好,一切都在代码里;期待老铁们加入,一起开发、一起折腾、一起快乐。 diff --git a/cmd/serve/serve.go b/cmd/serve/serve.go index abf859e3..66ff5156 100644 --- a/cmd/serve/serve.go +++ b/cmd/serve/serve.go @@ -62,6 +62,10 @@ func serveRun(_cmd *cobra.Command, _args []string) { // initial configure conf.Initial(features, noDefaultFeatures) + if cfg.If("loggerOtlp") { + shutdownFn, _ := conf.InitTelemetry() + defer shutdownFn() + } internal.Initial() ss := service.MustInitService() if len(ss) < 1 { diff --git a/config.yaml.sample b/config.yaml.sample index 635a9811..9a500c0a 100644 --- a/config.yaml.sample +++ b/config.yaml.sample @@ -87,19 +87,14 @@ LoggerFile: # 使用File写日志 SavePath: custom/data/paopao-ce/logs FileName: app FileExt: .log -LoggerZinc: # 使用Zinc写日志 - Host: zinc:4080 - Index: paopao-log - User: admin - Password: admin - Secure: False -LoggerMeili: # 使用Meili写日志 - Host: meili:7700 - Index: paopao-log - ApiKey: paopao-meilisearch - Secure: False - MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5 - MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100 +LoggerOtlp: # 使用OpenTelemetry写日志 + Endpoint: openobserve:5081 + Authorization: Basic ls8icEBvcGVub2JzFXJ2ZS6haCpZTU4ybGdBUFlXcjA0UdNk + Organization: paopao-ce + TraceStream: paopao-trace + MetricStream: paopao-metric + LogStream: paopao-log + Insecure: true JWT: # 鉴权加密 Secret: 18a6413dc4fe394c66345ebe501b2f26 Issuer: paopao-api diff --git a/features-status.md b/features-status.md index b2781944..e90345e3 100644 --- a/features-status.md +++ b/features-status.md @@ -111,7 +111,7 @@ * [x] 业务逻辑实现 #### 搜索: -* `Zinc` 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务(目前状态: 稳定,推荐使用); +* `Zinc` 基于[Zinc](https://github.com/zinclabs/zinc)搜索引擎提供推文搜索服务(目前状态: Deprecated); * [ ] 提按文档 * [x] 接口定义 * [x] 业务逻辑实现 @@ -129,18 +129,23 @@ * [ ] 提按文档 * [x] 接口定义 * [x] 业务逻辑实现 -* `LoggerZinc` 使用[Zinc](https://github.com/zinclabs/zinc)写日志(目前状态: 稳定,推荐使用); +* `LoggerZinc` 使用[Zinc](https://github.com/zinclabs/zinc)写日志(目前状态: Deprecated); * [ ] 提按文档 * [x] 接口定义 * [x] 业务逻辑实现 -* `LoggerMeili` 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志(目前状态: 内测阶段); +* `LoggerMeili` 使用[Meilisearch](https://github.com/meilisearch/meilisearch)写日志(目前状态: Deprecated); * [ ] 提按文档 * [x] 接口定义 * [x] 业务逻辑实现 -* `LoggerOpenObserve` 使用[OpenObserve](https://github.com/openobserve/openobserve)写日志(目前状态: 内测阶段); +* `LoggerOpenObserve` 使用[OpenObserve](https://github.com/openobserve/openobserve)写日志(目前状态: Deprecated); * [ ] 提按文档 * [x] 接口定义 * [x] 业务逻辑实现 +* `LoggerOtlp` 使用[OpenTelemetry](https://github.com/open-telemetry/opentelemetry-go)写日志(目前状态: 内测阶段); + * [ ] 提按文档 + * [x] 接口定义 + * [x] 业务逻辑实现 + #### 监控: * `Sentry` 使用Sentry进行错误跟踪与性能监控(目前状态: 内测); diff --git a/go.mod b/go.mod index ae2d514b..6f288973 100644 --- a/go.mod +++ b/go.mod @@ -42,10 +42,20 @@ require ( github.com/spf13/viper v1.19.0 github.com/tencentyun/cos-go-sdk-v5 v0.7.55 github.com/yinheli/mahonia v0.0.0-20131226213531-0eef680515cc + go.opentelemetry.io/contrib/bridges/otellogrus v0.9.0 + go.opentelemetry.io/contrib/instrumentation/runtime v0.59.0 + go.opentelemetry.io/otel v1.34.0 + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 + go.opentelemetry.io/otel/log v0.10.0 + go.opentelemetry.io/otel/sdk v1.34.0 + go.opentelemetry.io/otel/sdk/log v0.10.0 + go.opentelemetry.io/otel/sdk/metric v1.34.0 go.uber.org/automaxprocs v1.5.3 - golang.org/x/crypto v0.31.0 - google.golang.org/grpc v1.64.1 - google.golang.org/protobuf v1.34.2 + golang.org/x/crypto v0.32.0 + google.golang.org/grpc v1.69.4 + google.golang.org/protobuf v1.36.3 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/resty.v1 v1.12.0 gorm.io/driver/mysql v1.5.7 @@ -62,7 +72,8 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bits-and-blooms/bitset v1.12.0 // indirect github.com/bytedance/sonic/loader v0.2.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/clbanning/mxj v1.8.4 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect @@ -73,6 +84,7 @@ require ( github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.20.0 // indirect @@ -86,6 +98,7 @@ require ( github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect github.com/google/uuid v1.6.0 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect @@ -123,7 +136,7 @@ require ( github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/rogpeppe/go-internal v1.13.1 // indirect github.com/rs/xid v1.5.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -138,18 +151,24 @@ require ( github.com/ugorji/go/codec v1.2.12 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.52.0 // indirect + go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect + go.opentelemetry.io/otel/metric v1.34.0 // indirect + go.opentelemetry.io/otel/trace v1.34.0 // indirect + go.opentelemetry.io/proto/otlp v1.5.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect golang.org/x/image v0.0.0-20210216034530-4410531fe030 // indirect - golang.org/x/net v0.33.0 // indirect + golang.org/x/net v0.34.0 // indirect golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.28.0 // indirect + golang.org/x/sys v0.29.0 // indirect golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.24.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect diff --git a/go.sum b/go.sum index c92f21d5..3fdcccf5 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,10 @@ github.com/bytedance/sonic v1.12.6/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKz github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= @@ -89,6 +91,7 @@ github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -121,6 +124,8 @@ github.com/golang-migrate/migrate/v4 v4.18.1 h1:JML/k+t4tpHCpQTCAD62Nu43NUFzHY4C github.com/golang-migrate/migrate/v4 v4.18.1/go.mod h1:HAX6m3sQgcdO81tdjn5exv20+3Kb13cmGli1hrD6hks= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -137,6 +142,8 @@ github.com/grafana/pyroscope-go v1.2.0 h1:aILLKjTj8CS8f/24OPMGPewQSYlhmdQMBmol1d github.com/grafana/pyroscope-go v1.2.0/go.mod h1:2GHr28Nr05bg2pElS+dDsc98f3JTUh2f6Fz1hWXrqwk= github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -262,8 +269,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -305,8 +312,9 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= @@ -328,14 +336,38 @@ github.com/yinheli/mahonia v0.0.0-20131226213531-0eef680515cc/go.mod h1:Pcc297eV github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/contrib/bridges/otellogrus v0.9.0 h1:8WlIPjiMRU8Pg86+JoBjdzXOKp9bWt2M9qiVbjjFUsg= +go.opentelemetry.io/contrib/bridges/otellogrus v0.9.0/go.mod h1:bkQ7eZh+3ruXMBGR2UfReI0EjxtkcsjsmQKJTh1N2Is= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= -go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= -go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= -go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= -go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= -go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= -go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= +go.opentelemetry.io/contrib/instrumentation/runtime v0.59.0 h1:rfi2MMujBc4yowE0iHckZX4o4jg6SA67EnFVL8ldVvU= +go.opentelemetry.io/contrib/instrumentation/runtime v0.59.0/go.mod h1:IO/gfPEcQYpOpPxn1OXFp1DvRY0viP8ONMedXLjjHIU= +go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY= +go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0 h1:5dTKu4I5Dn4P2hxyW3l3jTaZx9ACgg0ECos1eAVrheY= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.10.0/go.mod h1:P5HcUI8obLrCCmM3sbVBohZFH34iszk/+CPWuakZWL8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 h1:ajl4QczuJVA2TU9W9AGw++86Xga/RKt//16z/yxPgdk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0/go.mod h1:Vn3/rlOJ3ntf/Q3zAI0V5lDnTbHGaUsNUeF6nZmm7pA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE= +go.opentelemetry.io/otel/log v0.10.0 h1:1CXmspaRITvFcjA4kyVszuG4HjA61fPDxMb7q3BuyF0= +go.opentelemetry.io/otel/log v0.10.0/go.mod h1:PbVdm9bXKku/gL0oFfUF4wwsQsOPlpo4VEqjvxih+FM= +go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ= +go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE= +go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A= +go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU= +go.opentelemetry.io/otel/sdk/log v0.10.0 h1:lR4teQGWfeDVGoute6l0Ou+RpFqQ9vaPdrNJlST0bvw= +go.opentelemetry.io/otel/sdk/log v0.10.0/go.mod h1:A+V1UTWREhWAittaQEG4bYm4gAZa6xnvVu+xKrIRkzo= +go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk= +go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w= +go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k= +go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= @@ -353,8 +385,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -379,8 +411,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -405,8 +437,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -436,12 +468,14 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= -google.golang.org/grpc v1.64.1 h1:LKtvyfbX3UGVPFcGqJ9ItpVWW6oN/2XqTxfAnwRRXiA= -google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA= +google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A= +google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4= +google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU= +google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/conf/conf.go b/internal/conf/conf.go index 4e1b513f..c21f51e8 100644 --- a/internal/conf/conf.go +++ b/internal/conf/conf.go @@ -17,6 +17,7 @@ var ( loggerZincSetting *loggerZincConf loggerMeiliSetting *loggerMeiliConf loggerOpenObserveSetting *loggerOpenObserveConf + loggerOtlpSetting *loggerOtlponf sentrySetting *sentryConf redisSetting *redisConf @@ -102,6 +103,7 @@ func setupSetting(suite []string, noDefault bool) error { "LoggerZinc": &loggerZincSetting, "LoggerMeili": &loggerMeiliSetting, "LoggerOpenObserve": &loggerOpenObserveSetting, + "LoggerOtlp": &loggerOtlpSetting, "Database": &DatabaseSetting, "MySQL": &MysqlSetting, "Postgres": &PostgresSetting, diff --git a/internal/conf/config.yaml b/internal/conf/config.yaml index 4d9c0185..8b25e260 100644 --- a/internal/conf/config.yaml +++ b/internal/conf/config.yaml @@ -152,7 +152,7 @@ LoggerMeili: # 使用Meili写日志 MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5 MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100 LoggerOpenObserve: # 使用OpenObserve写日志 - Host: 127.0.0.1:5080 + Host: openobserve:5080 Organization: paopao-ce Stream: default User: root@paopao.info @@ -160,6 +160,14 @@ LoggerOpenObserve: # 使用OpenObserve写日志 Secure: False MinWorker: 5 # 最小后台工作者, 设置范围[5, 100], 默认5 MaxLogBuffer: 100 # 最大log缓存条数, 设置范围[10, 10000], 默认100 +LoggerOtlp: # 使用OpenTelemetry写日志 + Endpoint: openobserve:5081 + Authorization: Basic ls8icEBvcGVub2JzFXJ2ZS6haCpZTU4ybGdBUFlXcjA0UdNk + Organization: paopao-ce + TraceStream: paopao-trace + MetricStream: paopao-metric + LogStream: paopao-log + Insecure: true JWT: # 鉴权加密 Secret: 18a6413dc4fe394c66345ebe501b2f26 Issuer: paopao-api diff --git a/internal/conf/logger.go b/internal/conf/logger.go index 3e999bf3..e2c6a60f 100644 --- a/internal/conf/logger.go +++ b/internal/conf/logger.go @@ -12,6 +12,7 @@ import ( "github.com/getsentry/sentry-go" sentrylogrus "github.com/getsentry/sentry-go/logrus" "github.com/sirupsen/logrus" + "go.opentelemetry.io/contrib/bridges/otellogrus" "gopkg.in/natefinch/lumberjack.v2" ) @@ -48,6 +49,10 @@ func setupLogger() { logrus.SetOutput(io.Discard) logrus.AddHook(hook) }, + "LoggerOtlp": func() { + hook := otellogrus.NewHook("main") + logrus.AddHook(hook) + }, }) } diff --git a/internal/conf/setting.go b/internal/conf/setting.go index c995edaa..fdcb3379 100644 --- a/internal/conf/setting.go +++ b/internal/conf/setting.go @@ -74,6 +74,16 @@ type loggerOpenObserveConf struct { MinWorker int } +type loggerOtlponf struct { + Endpoint string + Authorization string + Organization string + TraceStream string + MetricStream string + LogStream string + Insecure bool +} + type httpServerConf struct { RunMode string HttpIp string diff --git a/internal/conf/telemetry.go b/internal/conf/telemetry.go new file mode 100644 index 00000000..3bcc610e --- /dev/null +++ b/internal/conf/telemetry.go @@ -0,0 +1,149 @@ +// Copyright 2025 ROC. All rights reserved. +// Use of this source code is governed by a MIT style +// license that can be found in the LICENSE file. + +package conf + +import ( + "context" + "fmt" + "sync" + + "go.opentelemetry.io/contrib/instrumentation/runtime" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/log/global" + "go.opentelemetry.io/otel/propagation" + sdklog "go.opentelemetry.io/otel/sdk/log" + sdkmetric "go.opentelemetry.io/otel/sdk/metric" + sdkresource "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.27.0" +) + +var ( + resource *sdkresource.Resource + initResourcesOnce sync.Once +) + +func InitTelemetry() (shutdownFn func(), err error) { + s := loggerOtlpSetting + var ( + tp *sdktrace.TracerProvider + mp *sdkmetric.MeterProvider + lp *sdklog.LoggerProvider + ) + + if tp, err = initTracerProvider(s); err != nil { + return + } + if mp, err = initMeterProvider(s); err != nil { + return + } + if lp, err = initLoggerProvider(s); err != nil { + return + } + // Starting runtime instrumentation + if err = runtime.Start(); err != nil { + shutdownFn = func() { + fmt.Printf("skip shutdown by step of init telemetry occurs error:%s", err) + } + return + } + shutdownFn = func() { + ctx := context.Background() + tp.Shutdown(ctx) + mp.Shutdown(ctx) + lp.Shutdown(ctx) + } + return +} + +func initResource() *sdkresource.Resource { + initResourcesOnce.Do(func() { + extraResources, _ := sdkresource.New( + context.Background(), + sdkresource.WithContainer(), + sdkresource.WithHost(), + sdkresource.WithSchemaURL(semconv.SchemaURL), + sdkresource.WithAttributes(semconv.ServiceNameKey.String("jswhatx")), + ) + resource, _ = sdkresource.Merge( + sdkresource.Default(), + extraResources, + ) + }) + return resource +} + +func initTracerProvider(s *loggerOtlponf) (*sdktrace.TracerProvider, error) { + opts := []otlptracegrpc.Option{ + otlptracegrpc.WithEndpoint(s.Endpoint), + otlptracegrpc.WithHeaders(newOtlpHeaders(s.Authorization, s.Organization, s.TraceStream)), + } + if s.Insecure { + opts = append(opts, otlptracegrpc.WithInsecure()) + } + exporter, err := otlptracegrpc.New(context.Background(), opts...) + if err != nil { + return nil, fmt.Errorf("otlp trace grpc exporter failed: %w", err) + } + tp := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exporter), + sdktrace.WithResource(initResource()), + ) + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) + return tp, nil +} + +func initMeterProvider(s *loggerOtlponf) (*sdkmetric.MeterProvider, error) { + opts := []otlpmetricgrpc.Option{ + otlpmetricgrpc.WithEndpoint(s.Endpoint), + otlpmetricgrpc.WithHeaders(newOtlpHeaders(s.Authorization, s.Organization, s.MetricStream)), + } + if s.Insecure { + opts = append(opts, otlpmetricgrpc.WithInsecure()) + } + exporter, err := otlpmetricgrpc.New(context.Background(), opts...) + if err != nil { + return nil, fmt.Errorf("otlp metric grpc exporter failed: %w", err) + } + mp := sdkmetric.NewMeterProvider( + sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter)), + sdkmetric.WithResource(initResource()), + ) + otel.SetMeterProvider(mp) + return mp, nil +} + +func initLoggerProvider(s *loggerOtlponf) (*sdklog.LoggerProvider, error) { + opts := []otlploggrpc.Option{ + otlploggrpc.WithEndpoint(s.Endpoint), + otlploggrpc.WithHeaders(newOtlpHeaders(s.Authorization, s.Organization, s.LogStream)), + } + if s.Insecure { + opts = append(opts, otlploggrpc.WithInsecure()) + } + exporter, err := otlploggrpc.New(context.Background(), opts...) + if err != nil { + return nil, fmt.Errorf("otlp log grpc exporter failed: %w", err) + } + processor := sdklog.NewBatchProcessor(exporter) + provider := sdklog.NewLoggerProvider( + sdklog.WithProcessor(processor), + sdklog.WithResource(initResource()), + ) + global.SetLoggerProvider(provider) + return provider, nil +} + +func newOtlpHeaders(auth, org, stream string) map[string]string { + return map[string]string{ + "Authorization": auth, + "organization": org, + "stream-name": stream, + } +}