开源日志平台:Graylog部署及接入

一、部署Graylog

Graylog总共需要3个服务:graylog服务端、mongodb(存储graylog的配置)、elasticSeach(存储日志)
本文档部署方案介绍:

  • graylog服务端、mongodb(存储graylog的配置)使用docker-compose部署
  • elasticSeach 引用外部地址

1. 安装docker、安装docker-compose

这部分直接参考互联网上的教程:链接

2. 通过docker-compose部署graylog

服务器上新建一个 graylog的目录,并在该目录下新建 docker-compose.yml
开源日志平台:Graylog部署及接入

version: '3'
services:
  mongo:
    image: mongo:5.0
    container_name: mongo
    volumes:
      - /data/docker/graylog/mongo_data:/data/db
    networks:
      - graylog
    ports:
      - 27017:27017
    environment:
      - TZ=Asia/Shanghai
    healthcheck:
      test: ["CMD", "mongo", "--eval", "db.adminCommand('ping')"]
      interval: 30s
      timeout: 10s
      retries: 5

  graylog:
    image: graylog/graylog:5.2
    container_name: graylog
    depends_on:
      mongo:
        condition: service_healthy
    environment:
      - GRAYLOG_ROOT_PASSWORD_SHA2=xxxxx #sha2生成的密码,可以服务器通过命令获取:echo -n yournewpassword | sha256sum
      - GRAYLOG_PASSWORD_SECRET=xxxxx #随机生成的secret,长度超过32位,可以自己生成
      - GRAYLOG_HTTP_ENABLE_TLS=false
      - GRAYLOG_TIMEZONE=Asia/Shanghai
      - GRAYLOG_MONGO_URI=mongodb://mongo:27017/graylog
      - GRAYLOG_ELASTICSEARCH_VERSION=7
      - GRAYLOG_ELASTICSEARCH_HOSTS=http://es账户:es密码@es地址:9200
      - GRAYLOG_ELASTICSEARCH_USER=es账户
      - GRAYLOG_ELASTICSEARCH_PASSWORD=es密码
      - GRAYLOG_HTTP_EXTERNAL_URI=http://访问地址/
      - GRAYLOG_HTTP_PUBLISH_URI=http://访问地址/
      - GRAYLOG_PLUGIN_SYSTEM_LANGUAGESELECTOR_DEFAULT_LOCALE=zh_CN
      - TZ=Asia/Shanghai
    networks:
      - graylog
    ports:
      - "9000:9000"
      - "514:514"
      - "514:514/udp"
      - "12201:12201"
      - "12201:12201/udp"

volumes:
  mongo_data:
    driver: local
  graylog_data:
    driver: local

networks:
  graylog:
    driver: bridge

上面的配置根据自己的环境,重新配置。
注意点:elasticSearch如果存在账密的化,参考下GRAYLOG_ELASTICSEARCH_XXX这几个配置,进行调整。

3. 启动graylog

# 1. 启动执行
docker-compose up -d

# 2. 如果希望调整docker-compose.yml的配置,需要先关闭,再重启
## 2.1 先关闭graylog的应用
docker-compose down

## 2.2 修改完文件后,再执行启动命令
docker-compose up -d

# 3.查看启动日志,确认是否完成启动
docker logs mongo;
docker logs graylog;

4. 配置graylog

日志传输,建议采用UDP协议,其次包括graylog的踩坑记录,参考如下文档:
参考1
参考2

二、java应用接入Graylog

1. pom新增依赖

<!--logback gelf日志收集-->
<dependency>
    <groupId>biz.paluch.logging</groupId>
    <artifactId>logstash-gelf</artifactId>
    <version>1.15.0</version>
</dependency>

2. 配置logback.xml文件,同时增加traceId、spanId方便链路日志的追踪

a. 配置 Logback 以支持 MDC,在 logback.xml 中配置 GelfLogbackAppender,并确保包括 traceId 和 spanId 字段:

<configuration>

    <appender name="GELF" class="biz.paluch.logging.gelf.logback.GelfLogbackAppender">
        <host>udp:graylog的地址</host> <!-- graylog 服务器ip -->
        <port>graylog开放的端口</port> <!-- graylog udp端口 -->
        <version>1.1</version>
        <facility>自定义一个名称</facility>
        <extractStackTrace>true</extractStackTrace>
        <filterStackTrace>false</filterStackTrace>
        <mdcProfiling>true</mdcProfiling>
        <timestampPattern>yyyy-MM-dd HH:mm:ss,SSSS</timestampPattern>
        <maximumMessageSize>8192</maximumMessageSize>

        <!-- Include trace and span IDs -->
        <mdcFields>traceId,spanId</mdcFields>
        <dynamicMdcFields>mdc.*,(mdc|MDC)fields</dynamicMdcFields>
        <includeFullMdc>true</includeFullMdc>

    </appender>

    <root level="INFO">
        <appender-ref ref="GELF"/>
    </root>

    <logger name="com.yourcompany" level="DEBUG">
        <appender-ref ref="GELF"/>
    </logger>

</configuration>

b. 代码中 新增MDC过滤器

import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.UUID;

@Component
public class MDCFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 过滤器初始化,如果有需要
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        // 检查是否是HTTP请求
        if (request instanceof HttpServletRequest) {
            HttpServletRequest httpRequest = (HttpServletRequest) request;

            // 获取traceId,如果已经存在则使用,否则生成新的
            String traceId = httpRequest.getHeader("X-Trace-Id");
            if (traceId == null || traceId.isEmpty()) {
                traceId = UUID.randomUUID().toString();
            }

            // 生成新的spanId
            String spanId = UUID.randomUUID().toString();

            // 将traceId和spanId放入MDC
            MDC.put("traceId", traceId);
            MDC.put("spanId", spanId);
        }

        try {
            // 继续处理请求
            chain.doFilter(request, response);
        } finally {
            // 清理MDC
            MDC.remove("traceId");
            MDC.remove("spanId");
        }
    }

    @Override
    public void destroy() {
        // 过滤器销毁,如果有需要
    }
}

c. 代码中 注册MDC过滤器

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MDCFilterConfig {

    @Bean
    public FilterRegistrationBean<MDCFilter> loggingFilter() {
        FilterRegistrationBean<MDCFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new MDCFilter());
        registrationBean.addUrlPatterns("/*"); // 应用过滤器到所有路径
        return registrationBean;
    }

}

三、Graylog使用

可以针对关键字or具体字段进行检索、聚合、告警等操作,这里就不一一讲解了,大家可以自行尝试学习。
开源日志平台:Graylog部署及接入

Oinone社区 作者:冯, 天宇原创文章,如若转载,请注明出处:https://doc.oinone.top/install/13126.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(1)
冯, 天宇的头像冯, 天宇数式员工
上一篇 2024年5月30日 pm7:32
下一篇 2024年5月31日 am10:46

相关推荐

  • 【OceanBase】后端部署使用 OceanBase 数据库(海扬/OB)

    OceanBase 数据库配置 驱动配置 Maven配置(4.2.5.3版本可用) <oceanbase.version>2.4.14</oceanbase.version> <dependency> <groupId>com.oceanbase</groupId> <artifactId>oceanbase-client</artifactId> <version>${oceanbase.version}</version> </dependency> PS: oceanbase 驱动必须使用 2.4.5 版本或以上,低于此版本的驱动无法使用自增ID功能,无法正常启动。点击查看官方JDBC版本发布记录 JDBC连接配置 OceanBase – Oracle 版 pamirs: datasource: base: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.alipay.oceanbase.jdbc.Driver url: jdbc:oceanbase://10.xxx.xxx.xxx:1001/BASE?useServerPrepStmts=true&useOraclePrepareExecute=true&defaultFetchSize=4096 username: xxxxxx password: xxxxxx validConnectionCheckerClassName: com.alibaba.druid.pool.vendor.OracleValidConnectionChecker validationQuery: SELECT 1 FROM DUAL OceanBase – MySQL 版 pamirs: datasource: base: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.alipay.oceanbase.jdbc.Driver url: jdbc:oceanbase://10.xxx.xxx.xxx:1001/base username: xxxxxx password: xxxxxx 连接 URL 配置 点击查看官方JDBC连接配置说明 URL 格式(OceanBase – Oracle 版) jdbc:oceanbase://${host}:${port}/${database}?useServerPrepStmts=true&useOraclePrepareExecute=true&defaultFetchSize=4096 在jdbc连接配置时,useServerPrepStmts=true&useOraclePrepareExecute=true 必须配置,否则自增主键无法正常使用。 defaultFetchSize=4096 意味着在使用服务端预处理时,游标每次获取的结果集行数,驱动默认值为 10,在进行大量数据获取时会出现卡顿的现象,因此推荐使用 4096 作为其结果集大小。过大可能会导致 OOM,过小可能还是会出现卡顿,该值需要按实际情况进行配置。 其他连接参数如需配置,可自行查阅相关资料进行调优。 方言配置(OceanBase – Oracle 版) PS:OceanBase – MySQL 版无需配置方言,只需修改数据库连接即可正常使用。 pamirs方言配置 pamirs: dialect: ds: base: type: OceanBase version: 4.2.5.3 major-version: oracle-4.2 pamirs: type: OceanBase version: 4.2.5.3 major-version: oracle-4.2 plus: configuration: jdbc-type-for-null: "NULL" using-model-as-property: true using-statement-handler-dialect: true mapper: batch: collectionCommit default-batch-config: read: 500 write: 100 数据库版本 type version majorVersion 4.2.5.3 OceanBase 4.2.5.3 oracle-4.2 PS:由于方言开发环境为4.2.5.3版本,其他类似版本(4.x)原则上不会出现太大差异,如出现其他版本无法正常支持的,可在文档下方留言。 schedule方言配置 pamirs: event: enabled: true schedule: enabled: true dialect: type: Oracle version: 12.2 major-version: 12c type version majorVersion Oracle 12.2 12c PS:由于 schedule 的方言与 Oracle 数据库并无明显差异,OceanBase 数据库可以直接使用 Oracle 数据库方言。 其他配置(OceanBase – Oracle 版) 逻辑删除的值配置 pamirs: mapper: global: table-info: logic-delete-value: (CAST(SYSTIMESTAMP AS DATE) – TO_DATE('1970-01-01 08:00:00', 'YYYY-MM-DD HH24:MI:SS')) * 8640000000000

    2025年7月21日
    86400
  • 自定义表达式函数

    由于表达式内的函数在前后端都可能执行,所以同一个表达式需要前后端同时定义 后端表达式自定义 package pro.shushi.pamirs.demo.core.fun; import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.common.constants.NamespaceConstants; import java.util.Date; import java.util.List; import static pro.shushi.pamirs.meta.enmu.FunctionCategoryEnum.TEXT; import static pro.shushi.pamirs.meta.enmu.FunctionCategoryEnum.TIME; import static pro.shushi.pamirs.meta.enmu.FunctionLanguageEnum.JAVA; import static pro.shushi.pamirs.meta.enmu.FunctionOpenEnum.LOCAL; import static pro.shushi.pamirs.meta.enmu.FunctionSceneEnum.EXPRESSION; /** * 自定义函数 */ @Fun(NamespaceConstants.expression) public class DemoCustomFunctions { @Function.Advanced( displayName = "逗号分隔字符串数组", language = JAVA, builtin = true, category = TEXT ) @Function.fun("MY_COMMA") @Function(name = "MY_COMMA", scene = {EXPRESSION}, openLevel = LOCAL, summary = "函数示例: MY_COMMA(list)\n函数说明: 将字符串数组转为逗号分隔的字符串" ) public String myComma(List<String> list) { return StringUtils.join(list, ","); } @Function.Advanced( displayName = "根据出生算年龄", language = JAVA, builtin = true, category = TIME ) @Function.fun("CALC_AGE") @Function(name = "CALC_AGE", scene = {EXPRESSION}, openLevel = LOCAL, summary = "函数示例: CALC_AGE(birthDate)\n函数说明: 根据出生算年龄" ) public Integer calcAge(Date birthDate) { if (birthDate == null) { return 0; } return new DateTime().getYear() – new DateTime(birthDate).getYear(); } } 前端表达式定义 定义后导入到main.ts里,导入@kunlun/dependencies的代码之后 import { Expression } from '@kunlun/dependencies'; import dayjs from 'dayjs'; Expression.getInstance().registerFunction('MY_COMMA', ['array'], (list: string[]) => { return (list || []) .map((value) => { return `'${value}'`; }) .join(','); }); Expression.getInstance().registerFunction('CALC_AGE', ['string'], (birthDate: string) => { if (birthDate == null) { return 0; } return Math.ceil(dayjs().year() – dayjs(birthDate,…

    2024年7月10日
    2.0K00
  • nginx如何配置后端服务的负载均衡

    要在Nginx中实现对同一套服务部署两遍并且按比例分配请求,你可以利用Nginx的负载均衡功能。具体做法如下: 步骤 1: 配置 upstream 首先,在Nginx的配置文件(通常是/etc/nginx/nginx.conf或/etc/nginx/sites-available/default,具体路径可能因系统而异)中定义一个upstream块,列出你的两个服务实例。这里假设你的两个服务实例运行在相同的主机上,但监听不同的端口,例如8080和8081。 http { upstream backend { server 192.168.1.100:8091 weight=1; server 192.168.1.101:8091 weight=1; } # … } 在这个例子中,weight=1表示两个服务实例具有相同的权重,Nginx会尽量以1:1的比例分配请求给这两个实例。 步骤 2: 配置 location 或 server 块 接着,在配置文件中找到或添加一个server块,然后在其中的location指令内指定使用刚刚定义的upstream。 server { listen 80; server_name your.domain.com; location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } 这里的proxy_pass http://backend;告诉Nginx将请求转发到名为backend的upstream定义的服务器列表中。 步骤 3: 重启Nginx 最后,保存配置文件并重启Nginx以使更改生效。 sudo nginx -t # 先测试配置是否正确 sudo systemctl restart nginx # 或者 service nginx restart,取决于你的系统 注意事项 确保你的两个服务实例是完全独立且状态同步的,以避免数据不一致或服务故障。 使用weight参数可以调整分配策略,如果你想改变分配比例,可以通过修改weight值来实现。 考虑到高可用性,还可以配置max_fails和fail_timeout等参数来处理失败的后端连接。

    2024年6月5日
    1.4K00
  • Oinone平台部署及依赖说明(v5.1)

    概述 名词解释 业务工程包:指平台提供的内置基础包和内置功能包。 设计器工程包:指模型设计器、界面设计器、流程设计器等相关依赖包。 父POM:仅声明依赖包版本的pom文件 启动工程POM:仅声明具体依赖包的pom文件,一般不用于指定版本。 业务工程部署 Oinone平台向合作伙伴提供前后端业务工程所需的全部依赖,依赖项的具体说明下面会分别介绍。 设计器部署 Oinone平台向合作伙伴提供了两种设计器部署方式: Docker镜像:支持amd64和arm64两种架构的操作系统。(推荐) JAR包:与Docker镜像中的内容完全一致。 使用JAR包直接启动需要使用Oinone专属启动器,Docker镜像已内置Oinone专属启动器。 PS:如遇到以上部署方式或提供的镜像无法满足部署需求时,请联系Oinone平台售后获取技术支持。 Docker镜像 体验镜像 包括所有设计器。 内置所有所需中间件,包括Mysql、Redis、Zookeeper、RocketMQ。 适用场景:用于快速体验Oinone平台全部功能 docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.1:TAG 前后端一体部署镜像 包括所有设计器。 无内置中间件。 适用场景:用于便捷部署Oinone平台的前后端服务 docker pull harbor.oinone.top/oinone/oinone-designer-mini-v5.1:TAG 前后端一体部署镜像 – 流程设计器 仅包括流程设计器。 无内置中间件。 适用场景:用于便捷部署仅需流程设计器的Oinone平台的前后端服务。 docker pull harbor.oinone.top/oinone/workflow-designer-v5.1:TAG 后端部署镜像 用于前后端分别部署,包括所有设计器。 仅包含后端服务 无内置中间件 适用场景:Kubenetes部署;支持健康检查,前后端分离部署; docker pull harbor.oinone.top/oinone/designer-backend-v5.1:TAG 前端部署镜像 用于前后端分别部署,包括所有设计器。 仅包含前端服务 无内置中间件 适用场景:Kubenetes部署;支持健康检查,前后端分离部署; docker pull harbor.oinone.top/oinone/designer-frontend-v5.1:TAG 镜像拉取 以体验镜像为例,Oinone平台提供多种拉取镜像的方式。 # 获取混合架构镜像,支持amd64和arm64架构的操作系统 docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.1:5.1.13 # 仅获取amd64架构镜像 docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.1:5.1.13-amd64 # 仅获取arm64架构镜像 docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.1:5.1.13-arm64 # 获取最新版镜像(每次拉取自动更新) docker pull harbor.oinone.top/oinone/oinone-designer-full-v5.1 PS:如镜像拉取过慢,可在确定操作系统架构的情况下获取amd64或arm64架构镜像。 JAR包获取 $VERSION:对应镜像版本号 包含所有设计器的后端JAR包下载路径示例 https://oinone-jar.oss-cn-zhangjiakou.aliyuncs.com/install/oinone-designer/pamirs-designer-boot-v5.1-$VERSION.jar 仅包含流程设计器的后端JAR包下载路径示例 https://oinone-jar.oss-cn-zhangjiakou.aliyuncs.com/install/workflow-designer/pamirs-workflow-designer-boot-v5.1-$VERSION.jar Kubernetes后端部署健康检查 准备健康检查脚本 将以下脚本放置在镜像中。/opt/pamirs/bin/healthCheck.sh为以下示例中所用脚本路径。(平台提供的设计器镜像有内置该脚本,并与示例路径一致) #!/usr/bin/env bash function sendDingTalkMessage() { url=$DING_TALK_ROBOT_URL if [ -z $url ]; then return -1 fi message=$DING_TALK_ROBOT_MESSAGE if [ -z $message ]; then return -1 fi message="$message\\nby kubernetes" isAtAll=$DING_TALK_ROBOT_IS_AT_ALL if [ $isAtAll ]; then isAtAll="true" message="$message\\n" else isAtAll="false" fi message="{\"msgtype\": \"text\",\"text\": {\"content\":\"$message\"}, \"isAtAll\": \"${isAtAll}\"}" curl "${url}" -H 'Content-Type: application/json' -d "${message}" } port=$1 callback=$2 OK=$(curl -s http://127.0.0.1:${port}/ruok) if [ "$OK" == "imok" ]; then if [ -n $callback ]; then $callback fi exit 0 else exit 1 fi 配置Kubernetes健康检查 kind: Deployment apiVersion: apps/v1 spec: template: spec: containers: – name: designer-backend env: – name: DING_TALK_ROBOT_URL #…

    2024年9月18日
    1.4K00
  • 如何配置文件存储地址为相对路径

    介绍 大部分情况下,文件存储的配置都会配置uploadUrl和downloadUrl的值,这样图片和文件类型的业务字段会存储带域名的全路径文件地址,但是有些场景需要用户在专有内网的时候访问内网的文件存储地址,用户在公网的时候通过公网访问(一般情况下这个公网ip内部最后还是会转发到内网)文件存储地址,这个时候就要求存在数据库字段里的不能是全路径的地址,只能是想相对路径,这个时候可以通过前端访问的域名用nginx转发当前域名下的文件请求到所匹配环境的ip内的文件存储服务。 配置参考 cdn: oss: name: 本地文件NG系统 type: LOCAL bucket: pamirs # 此处可以不配置值,也可以配置相对路径前缀方便做转发 uploadUrl: downloadUrl: validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: /test/static 文件上传的路径同步配置nginx转发 location ~ /file/upload { // 此处配置为后端服务的ip+端口 proxy_pass http://127.0.0.1:8190; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } excel导入场景相对路径在后端代码内无法保存导入的文件 在导入任务的前置hook处理相对文件路径的前缀 package pro.shushi.pamirs.demo.core.hook; import org.apache.commons.lang.StringUtils; import org.springframework.stereotype.Component; import pro.shushi.pamirs.file.api.FileModule; import pro.shushi.pamirs.file.api.model.ExcelImportTask; import pro.shushi.pamirs.meta.annotation.Hook; import pro.shushi.pamirs.meta.api.core.faas.HookBefore; import pro.shushi.pamirs.meta.api.dto.fun.Function; @Component public class DemoExcelImportTaskActionHookBefore implements HookBefore { // 内网访问文件的地址 public static final String INNER_HOST = "http://127.0.0.1:6800"; @Override @Hook(module = {FileModule.MODULE_MODULE}, model = {ExcelImportTask.MODEL_MODEL}, fun = {"createImportTask"}) public Object run(Function function, Object… args) { if (args.length > 0) { ExcelImportTask excelImportTask = (ExcelImportTask) args[0]; if (excelImportTask != null && excelImportTask.getFile() != null && StringUtils.isNotBlank(excelImportTask.getFile().getUrl())) { excelImportTask.getFile().setUrl(INNER_HOST + excelImportTask.getFile().getUrl()); } } return null; } } 注意事项 上面的例子为本地文件NG系统的,如果是阿里云oss、7牛云等第三方文件存储服务,downloadUrl可以按上面方案直接配置,uploadUrl还是要按正常配置

    2024年6月21日
    1.9K00

Leave a Reply

登录后才能评论