平台配置日志输出和推送到APM与LogStash

场景描述

目前设计器镜像启动后日志文件为out.log,是启动脚本中定向输出了(>>)out.log文件。实际项目可能:

  • 日志输出到特定目录的特定文件名中
  • 指定以日志保留策略(单个文件大小和文件保留个数)
  • 日志输出到APM工具中(如skywalking)
  • 日志推送到LogStash

日志自定义输出

不定向输出,采用自己配置的方式,与标准的SpringBoot工程配置日志一样。两种方式(都是Spring提供的方式):

方式一

bootstrap.yml 里面可以按profiles指定logback的配置文件,具体文件名和文件输入在logback里面进行配置,跟通用的logback配置一致. 例如:

logging:
  config: classpath:logback-pre.xml

方式二

resources的根目录,直接配置 logback-spring.xml, 启动会自动加载。

日志自定义场景

配置日志推送到LogStash

    <!--配置日志推送到LogStash-->
    <contextListener class="pro.shushi.pamirs.demo.core.config.DemoLogbackFiledConfig"/>
    <appender name="LogStash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>127.0.0.1:4560</destination>
        <!-- encoder必须配置,有多种可选 -->
        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
            <!--  SkyWalking插件, log加tid-->
            <provider class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.logstash.TraceIdJsonProvider" />
            <!--在生成的json中会加这些字段-->
            <customFields>
                {"app.name":"pamirs-demo", "app.type":"Microservice", "platform":"pamirs", "env":"dev"}
            </customFields>
            <timeZone>Asia/Shanghai</timeZone>
            <writeVersionAsInteger>true</writeVersionAsInteger>
            <providers>
                <pattern>
                    <pattern>
                        <!--动态的变量-->
                        {
                        "ip": "%{ip}",
                        "server.name": "%{server.name}",
                        "logger_name": "%logger"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>

skywalking的日志rpc上传

    <!-- skywalking的日志rpc上传 -->
    <appender name="SkyWalkingLogs" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
                <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            </layout>
        </encoder>
    </appender>

完整的代码示例

  • Logback自定义字段
package pro.shushi.pamirs.demo.core.config;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.core.Context;
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.spi.LifeCycle;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 *  Logback自定义字段
 *
 * @author wx@shushi.pro
 * @date 2024/4/17
 */
public class DemoLogbackFiledConfig extends ContextAwareBase implements LoggerContextListener, LifeCycle {

    private boolean started = false;

    @Override
    public boolean isResetResistant() {
        return false;
    }

    @Override
    public void onStart(LoggerContext loggerContext) {
    }

    @Override
    public void onReset(LoggerContext loggerContext) {
    }

    @Override
    public void onStop(LoggerContext loggerContext) {
    }

    @Override
    public void onLevelChange(Logger logger, Level level) {
    }

    @Override
    public void start() {
        if (started) {
            return;
        }
        Context context = getContext();
        // 机器名称
        context.putProperty("server.name", getHostName());
        // 机器IP地址
        context.putProperty("ip", getHostAddress());
        started = true;
    }

    @Override
    public void stop() {
    }

    @Override
    public boolean isStarted() {
        return false;
    }

    private String getHostName() {
        try {
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return "";
    }

    private String getHostAddress() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return "";
    }
}
  • logback-dev.xml完整内容
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 日志输出格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="%d |-%p [%tid] %class:%line - %m%n"/>

    <!-- 控制台日志 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <pattern>${CONSOLE_LOG_PATTERN}</pattern><!-- 此处设置输出格式 -->
            </layout>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
    </appender>

    <!-- 文件日志 -->
    <appender name="fileLogger"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>/Users/wangxian/logs/pamirs-demo.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/Users/wangxian/logs/pamirs-demo-%d-%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- 日志文件的最多存储64MB -->
                <maxFileSize>500MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
           <!--日志文件保留天数-->
            <maxHistory>15</maxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
                <pattern>${CONSOLE_LOG_PATTERN}</pattern><!-- 此处设置输出格式 -->
            </layout>
            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
        </encoder>
    </appender>

    <!--配置日志推送到LogStash-->
    <contextListener class="pro.shushi.pamirs.demo.core.config.DemoLogbackFiledConfig"/>
    <appender name="LogStash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>127.0.0.1:4560</destination>
        <!-- encoder必须配置,有多种可选 -->
        <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
            <!--  SkyWalking插件, log加tid-->
            <provider class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.logstash.TraceIdJsonProvider" />
            <!--在生成的json中会加这些字段-->
            <customFields>
                {"app.name":"pamirs-demo", "app.type":"Microservice", "platform":"pamirs", "env":"dev"}
            </customFields>
            <timeZone>Asia/Shanghai</timeZone>
            <writeVersionAsInteger>true</writeVersionAsInteger>
            <providers>
                <pattern>
                    <pattern>
                        <!--动态的变量-->
                        {
                        "ip": "%{ip}",
                        "server.name": "%{server.name}",
                        "logger_name": "%logger"
                        }
                    </pattern>
                </pattern>
            </providers>
        </encoder>
    </appender>

    <!-- skywalking的日志rpc上传 -->
    <appender name="SkyWalkingLogs" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
                <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            </layout>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="LogStash"/>
        <appender-ref ref="SkyWalkingLogs"/>
    </root>

    <!-- Nacos的心跳检测日志级别设置 (会自动继承root 的appender) -->
    <logger name="com.alibaba" level="ERROR">
    </logger>
    <!-- xxl-job心跳检查日志级别 -->
    <logger name="com.xxl.job.core.thread" level="ERROR"/>
</configuration>
  • 分为debug、info、warn、error四种类型的日志信息,分别保存到此四个文件夹中,并按大小和日期进行归档
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->

<!-- 根节点<configuration>,包含下面三个属性:-->
<!-- scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。-->
<!-- scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。-->
<!-- debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。-->
<configuration>
   <contextName>dimples-logback</contextName>
   <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
   <property name="log.path" value="C:/springboot-log/logs" />

   <!-- 彩色日志 -->
   <!-- 彩色日志依赖的渲染类 -->
   <conversionRule conversionWord="clr"
      converterClass="org.springframework.boot.logging.logback.ColorConverter" />
   <conversionRule conversionWord="wex"
      converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
   <conversionRule conversionWord="wEx"
      converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
   <!-- 彩色日志格式 -->
   <property name="CONSOLE_LOG_PATTERN"
      value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
   <property name="log.colorPattern" value="%magenta(%d{yyyy-MM-dd HH:mm:ss}) %highlight(%-5level) %boldCyan([${springAppName:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]) %yellow(%thread) %green(%logger) %msg%n"/>
   <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level [${springAppName:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}] %thread %logger %msg%n"/>
   <!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,%i索引【从数字0开始递增】,,, -->
   <!-- appender是configuration的子节点,是负责写日志的组件。 -->
   <!-- ConsoleAppender:把日志输出到控制台 -->
   <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
      <encoder>
         <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
         <!-- 控制台也要使用UTF-8,不要使用GBK,否则会中文乱码 -->
         <charset>UTF-8</charset>
      </encoder>
   </appender>

   <!-- 时间滚动输出 level为 DEBUG 日志 -->
   <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
      <!-- 正在记录的日志文件的路径及文件名 -->
      <file>${log.path}\debug/log_debug.log</file>
      <!--日志信息输出格式-->
      <encoder>
         <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
         <charset>UTF-8</charset> <!-- 设置字符集 -->
      </encoder>
      <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
         <!-- 日志归档 -->
         <fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd-HH}.%i.log</fileNamePattern>
         <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <maxFileSize>100MB</maxFileSize>
         </timeBasedFileNamingAndTriggeringPolicy>
         <!--日志文件保留天数-->
         <maxHistory>15</maxHistory>
      </rollingPolicy>
      <!-- 此日志文件只记录debug级别的 -->
      <filter class="ch.qos.logback.classic.filter.LevelFilter">
         <level>debug</level>
         <onMatch>ACCEPT</onMatch>
         <onMismatch>DENY</onMismatch>
      </filter>
   </appender>

   <!-- 时间滚动输出 level为 INFO 日志 -->
   <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
      <!-- 正在记录的日志文件的路径及文件名 -->
      <file>${log.path}\info/log_info.log</file>
      <!--日志信息输出格式-->
      <encoder>
         <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
         <charset>UTF-8</charset>
      </encoder>
      <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
         <!-- 每天日志归档路径以及格式 -->
         <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd-HH}.%i.log</fileNamePattern>
         <timeBasedFileNamingAndTriggeringPolicy
            class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <maxFileSize>100MB</maxFileSize>
         </timeBasedFileNamingAndTriggeringPolicy>
         <!--日志文件保留天数-->
         <maxHistory>15</maxHistory>
      </rollingPolicy>
      <!-- 此日志文件只记录info级别的 -->
      <filter class="ch.qos.logback.classic.filter.LevelFilter">
         <level>info</level>
         <onMatch>ACCEPT</onMatch>
         <onMismatch>DENY</onMismatch>
      </filter>
   </appender>

   <!-- 时间滚动输出 level为 WARN 日志 -->
   <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
      <!-- 正在记录的日志文件的路径及文件名 -->
      <file>${log.path}\warn/log_warn.log</file>
      <!--日志信息输出格式-->
      <encoder>
         <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
         <charset>UTF-8</charset> <!-- 此处设置字符集 -->
      </encoder>
      <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
         <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd-HH}.%i.log</fileNamePattern>
         <timeBasedFileNamingAndTriggeringPolicy
            class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <maxFileSize>100MB</maxFileSize>
         </timeBasedFileNamingAndTriggeringPolicy>
         <!--日志文件保留天数-->
         <maxHistory>30</maxHistory>
      </rollingPolicy>
      <!-- 此日志文件只记录warn级别的 -->
      <filter class="ch.qos.logback.classic.filter.LevelFilter">
         <level>warn</level>
         <onMatch>ACCEPT</onMatch>
         <onMismatch>DENY</onMismatch>
      </filter>
   </appender>
   <!-- RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->
   <!--             2.如果日期没有发生变化,但是当前日志的文件大小超过1KB时,对当前日志进行分割 重命名-->
   <!-- 时间滚动输出 level为 ERROR 日志 -->
   <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
      <!-- 正在记录的日志文件的路径及文件名 -->
      <file>${log.path}\error/log_error.log</file>
      <!--日志信息输出格式-->
      <encoder>
         <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
         <charset>UTF-8</charset> <!-- 此处设置字符集 -->
      </encoder>
      <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
      <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
         <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd-HH}.%i.log</fileNamePattern>
         <timeBasedFileNamingAndTriggeringPolicy
            class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
            <maxFileSize>100MB</maxFileSize>
         </timeBasedFileNamingAndTriggeringPolicy>
         <!--日志文件保留天数-->
         <maxHistory>30</maxHistory>
      </rollingPolicy>
      <!-- 此日志文件只记录ERROR级别的 -->
      <filter class="ch.qos.logback.classic.filter.LevelFilter">
         <level>ERROR</level>
         <onMatch>ACCEPT</onMatch>
         <onMismatch>DENY</onMismatch>
      </filter>
   </appender>
   <!--开发环境:打印控制台-->
   <!-- 指定项目中某个包,当有日志操作行为时的日志记录级别 -->
   <!-- com.dimples.springboot.biz为业务逻辑根包,也就是只要是发生在这个根包下面的所有日志操作行为的权限都是DEBUG -->
   <!-- 级别依次为【从高到低】:FATAL > ERROR > WARN > INFO > DEBUG > TRACE  -->
   <springProfile name="dev">
      <logger name="com.dimples.springboot.biz" level="debug" />
   </springProfile>
   <!-- 控制台输出日志级别 -->
   <root level="info">
      <appender-ref ref="CONSOLE" />
      <appender-ref ref="DEBUG_FILE" />
      <appender-ref ref="INFO_FILE" />
      <appender-ref ref="WARN_FILE" />
      <appender-ref ref="ERROR_FILE" />
   </root>

   <!--生产环境:输出到文件-->
   <!--<springProfile name="pro">-->
   <!--<root level="info">-->
   <!--<appender-ref ref="CONSOLE" />-->
   <!--<appender-ref ref="DEBUG_FILE" />-->
   <!--<appender-ref ref="INFO_FILE" />-->
   <!--<appender-ref ref="ERROR_FILE" />-->
   <!--<appender-ref ref="WARN_FILE" />-->
   <!--</root>-->
   <!--</springProfile>-->
</configuration>

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

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

(0)
望闲的头像望闲数式管理员
上一篇 2024年5月18日 pm3:14
下一篇 2024年5月18日 pm4:45

相关推荐

  • Centos7 部署mysql8详细教程

    安装前准备 1.访问mysql官网下载mysql8软件包 https://dev.mysql.com/downloads/mysql/选择相应的版本如:RPM Bundle mysql-8.0.33-1.el7.x86_64.rpm-bundle.tarRPM Bundle 8.0.33 下载地址:https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar 2.卸载MariaDB [root@haibovm ~]# rpm -qa | grep mariadb mariadb-libs-5.5.60-1.el7_5.x86_64 [root@haibovm ~]# rpm -e –nodeps mariadb-libs-5.5.60-1.el7_5.x86_64 3.检查 libaio numactl 是否安装 [root@haibovm ~]# rpm -qa|grep libaio libaio-0.3.109-13.el7.x86_64 [root@haibovm ~]# rpm -qa|grep numactl numactl-libs-2.0.9-7.el7.x86_64 如果没有检测到请使用以下命令安装 [root@haibovm ~]# yum install libaio numactl -y 4.关闭防火墙selinux(根据自身情况) [root@haibovm ~]# sed -i 's/enforcing/disabled/' /etc/selinux/config [root@haibovm ~]# setenforce 0 [root@haibovm ~]# systemctl stop firewalld [root@haibovm ~]# systemctl disable firewalld Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service. Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service. [root@haibovm ~]# systemctl is-active firewalld unknown 5.防火墙开放端口 [root@haibovm ~]# firewall-cmd –zone=public –add-port=3306/tcp –permanent # 开放3306端口 [root@haibovm ~]# firewall-cmd –zone=public –remove-port=3306/tcp –permanent #关闭3306端口 [root@haibovm ~]# firewall-cmd –reload # 配置立即生效 [root@haibovm ~]# firewall-cmd –zone=public –list-ports # 查看防火墙所有开放的端口 安装mysql8 1.下载mysql8到/opt目录 [root@haibovm ~]# cd /opt/ [root@haibovm opt]# yum install wget -y && wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar 2.解压 mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar [root@haibovm opt]# tar -xvf mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar mysql-community-client-8.0.33-1.el7.x86_64.rpm mysql-community-client-plugins-8.0.33-1.el7.x86_64.rpm mysql-community-common-8.0.33-1.el7.x86_64.rpm mysql-community-debuginfo-8.0.33-1.el7.x86_64.rpm mysql-community-devel-8.0.33-1.el7.x86_64.rpm mysql-community-embedded-compat-8.0.33-1.el7.x86_64.rpm mysql-community-icu-data-files-8.0.33-1.el7.x86_64.rpm mysql-community-libs-8.0.33-1.el7.x86_64.rpm mysql-community-libs-compat-8.0.33-1.el7.x86_64.rpm mysql-community-server-8.0.33-1.el7.x86_64.rpm mysql-community-server-debug-8.0.33-1.el7.x86_64.rpm mysql-community-test-8.0.33-1.el7.x86_64.rpm 3.安装 community-common [root@haibovm opt]# rpm -ivh –nodeps –force mysql-community-common-8.0.33-1.el7.x86_64.rpm 警告:mysql-community-common-8.0.33-1.el7.x86_64.rpm: 头V4 RSA/SHA256 Signature, 密钥 ID 3a79bd29: NOKEY 准备中… ################################# [100%] 正在升级/安装… 1:mysql-community-common-8.0.33-1.e################################# [100%] 4.安装 community-libs [root@haibovm opt]# rpm -ivh –nodeps –force mysql-community-libs-8.0.33-1.el7.x86_64.rpm 警告:mysql-community-libs-8.0.33-1.el7.x86_64.rpm: 头V4 RSA/SHA256 Signature, 密钥…

    2023年11月7日
    1.0K00
  • IWrapper、QueryWrapper和LambdaQueryWrapper使用

    条件更新updateByWrapper 通常我们在更新的时候new一个对象出来在去更新,减少更新的字段 Integer update = new DemoUser().updateByWrapper(new DemoUser().setFirstLogin(Boolean.FALSE), Pops.<DemoUser>lambdaUpdate().from(DemoUser.MODEL_MODEL).eq(IdModel::getId, userId) 使用基础模型的updateById方法更新指定字段的方法: new 一下update对象出来,更新这个对象。 WorkflowUserTask userTaskUp = new WorkflowUserTask(); userTaskUp.setId(userTask.getId()); userTaskUp.setNodeContext(json); userTaskUp.updateById(); 条件删除updateByWrapper public List<T> delete(List<T> data) { List<Long> petTypeIdList = new ArrayList(); for(T item:data){ petTypeIdList.add(item.getId()); } Models.data().deleteByWrapper(Pops.<PetType>lambdaQuery().from(PetType.MODEL_MODEL).in(PetType::getId,petTypeIdList)); return data; } 构造条件查询数据 示例1: LambdaQueryWrapper拼接查询条件 private void queryPetShops() { LambdaQueryWrapper<PetShop> query = Pops.<PetShop>lambdaQuery(); query.from(PetShop.MODEL_MODEL); query.setSortable(Boolean.FALSE); query.orderBy(true, true, PetShop::getId); List<PetShop> petShops2 = new PetShop().queryList(query); System.out.printf(petShops2.size() + ""); } 示例2: IWrapper拼接查询条件 private void queryPetShops() { IWrapper<PetShop> wrapper = Pops.<PetShop>lambdaQuery() .from(PetShop.MODEL_MODEL).eq(PetShop::getId,1L); List<PetShop> petShops4 = new PetShop().queryList(wrapper); System.out.printf(petShops4.size() + ""); } 示例3: QueryWrapper拼接查询条件 private void queryPetShops() { //使用Lambda获取字段名,防止后面改字段名漏改 String nameField = LambdaUtil.fetchFieldName(PetTalent::getName); //使用Lambda获取Clumon名,防止后面改字段名漏改 String nameColumn = PStringUtils.fieldName2Column(nameField); QueryWrapper<PetShop> wrapper2 = new QueryWrapper<PetShop>().from(PetShop.MODEL_MODEL) .eq(nameColumn, "test"); List<PetShop> petShops5 = new PetShop().queryList(wrapper2); System.out.printf(petShops5.size() + ""); } IWrapper转为LambdaQueryWrapper @Function.Advanced(type= FunctionTypeEnum.QUERY) @Function.fun(FunctionConstants.queryPage) @Function(openLevel = {FunctionOpenEnum.API}) public Pagination<PetShopProxy> queryPage(Pagination<PetShopProxy> page, IWrapper<PetShopProxy> queryWrapper) { LambdaQueryWrapper<PetShopProxy> wrapper = ((QueryWrapper<PetShopProxy>) queryWrapper).lambda(); // 非存储字段从QueryData中获取 Map<String, Object> queryData = queryWrapper.getQueryData(); if (null != queryData && !queryData.isEmpty()) { String codes = (String) queryData.get("codes"); if (org.apache.commons.lang3.StringUtils.isNotBlank(codes)) { wrapper.in(PetShopProxy::getCode, codes.split(",")); } } return new PetShopProxy().queryPage(page, wrapper); }

    2024年5月25日
    2.2K00
  • Docker部署常见问题

    问题1:容器启动出现library initialization failed – unable to allocate file descriptor table – out of memory异常如何处理? 原因 不同操作系统安装Docker后,容器运行环境并不一致,需要对Docker运行参数进行调整。 解决方案 编辑/etc/systemd/system/docker.service文件, 有些系统该文件位置:/lib/systemd/system/docker.service 查看docker的systemd(docker.service)配置位置 systemctl status docker 查看docker的systemd配置位置 将下列参数进行修改 LimitNOFILE=65535 LimitNPROC=65535 LimitCORE=65535 执行以下脚本 systemctl daemon-reload systemctl restart docker 问题2:容器启动出现library initialization failed – unable to allocate file descriptor table – out of memorypanic: signal: aborted (core dumped)异常如何处理? 问题现象 1、 按照【问题1】的设置进行配置后,仍然不生效; 2、 尝试修改宿主机系统内核的ulimits,重启docker仍报错。修改docker.service(文件位置:/etc/systemd/system/docker.service文件, 有些系统该文件位置:/lib/systemd/system/docker.service) 解决方案 查看docker的systemd(docker.service)配置位置【问题1】中的办法 在ExecStart命令后加上创建容器的默认ulimit配置,如下,设置容器启动时的ulimit为65535:65535 –default-ulimit nofile=65535:65535 配置好后: ExecStart=/usr/bin/dockerd -H fd:// –containerd=/run/containerd/containerd.sock –default-ulimit nofile=65535:65535 执行以下脚本 systemctl daemon-reload systemctl restart docker 资料参考:https://blog.csdn.net/weixin_42241322/article/details/137122868 问题3:拉取设计器镜像报错 报错信息,拉取镜像harbor.oinone.top连不上。 docker login –username=schhsw_oinone harbor.oinone.top i Info → A Personal Access Token (PAT) can be used instead. To create a PAT, visit https://app.docker.com/settings Password: time="2025-02-27T11:24:58+08:00" level=info msg="Error logging in to endpoint, trying next endpoint" error="Get \"https://harbor.oinone.top/v2/\": dial tcp 0.0.0.0:443: connect: connection refused" Get "https://harbor.oinone.top/v2/": dial tcp 0.0.0.0:443: connect: connection refused kfpt@kfpt-virtual-machine:~$ sudo -i root@kfpt-virtual-machine:~# docker login –username=schhsw_oinone harbor.oinone.top i Info → A Personal Access Token (PAT) can be used instead. To create a PAT, visit https://app.docker.com/settings Password: Error response from daemon: Get "https://harbor.oinone.top/v2/": dial tcp 0.0.0.0:443: connect: connection refused 排查过程: 排除到后面发现原因是DNS配置的问题,换了一个阿里云的IP就可以了

    2025年3月13日
    1.3K00
  • 协同开发支持

    协同开发概述 在使用Oinone进行业务开发中,目前开发方式为: 开发各个本地启动项目 与 设计器环境共库共redis的方式进行。 在多个开发人员同时修改一个模型,或者没有及时更新其他同学提交的代码时,存在业务模型创建的数据表字段被删除的情况,协同开发模式正式为解决这个问题而生。 版本支持 4.7.x版本 已经包含分布式支持。 使用步骤 1、业务后端boot工程引入协同开发包 <dependency> <groupId>pro.shushi.pamirs.distribution</groupId> <artifactId>pamirs-distribution-session-cd</artifactId> </dependency> 2、yml文件配置ownSign pamirs: distribution: session: allMetaRefresh: false # ownSign根据实际情况修改,一般为研发各自名称 ownSign: wangxian 配置说明:allMetaRefresh,全量刷新Redis中的元数据,绝大多数情况下都不需要配置;1)第一次启动或者Redis的缓存被清空后,会自动进行全量。2)配置为true表示强制进行全量,一般都不需要配置;3)【推荐】默认增量的方式(即allMetaRefresh: false)写入redis的数据更少,相应的启动速度也更快4)【强制】ownSign是环境隔离的设置,同一个项目组不同的开发人员之间,ownSign配置成不同的(即各自配置成各自的,达到互不干扰) 3、业务系统DB和缓存的约束1)【强制】业务库和设计器Redis共用,包括Redis的前缀,租户和系统隔离键都需要一样(这三个值影响RedisKey的拼接)2)【强制】base库业务系统与设计器共用;3) 【强制】公共库即pamirs (资源-resource、用户-user、权限-auth、文件-file等)共用;4)【强制】「业务库」数据源的别名必须一直,每个开发人员必须配置到自己的本地 或者是远程库库加一个后缀区分; 4、开发同学在各自访问设计器时,URL最后面增加;ownSign=wangxian后回车,ownSign会被保存到浏览器缓存中,后续访问其他的URL访问不需要再次输入;如果需要去掉ownSign的值,则直接把界面上的悬浮窗删掉即可。说明:访问设计URL上增加的ownSign需要与开发各自本地项目yml文件中ownSign的值相同。(每个开发人员各自用各自的ownSign)PS:具体参数配置详见Oinone协同开发使用手册

    2023年12月4日
    1.7K00
  • 如何配置文件存储地址为相对路径

    介绍 大部分情况下,文件存储的配置都会配置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日
    2.0K00

Leave a Reply

登录后才能评论