質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.34%

Mybatisで使用するSQLの出力制御について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 8,941

score 25

いつもお世話になっております。

現在、Springboo2、PostgreSQL、Mybatis、Logbackで開発をしております。
Mybatisで実施したSQL、バインド変数などをログに出力したい為に、
logback-spring.xmlに以下の記述をして、ログを出力するようにしました。

このログの出力でお聞きしたい事があります。
毎回ログを出力せずに、必要な時だけログを出力したいのですが、
logback-spring.xml以外(プログラムからになります)から、
ログレベルなどを変更して、ログを出力する/出力しないといった制御を実施したいのですが、
出来るのでしょうか。

  <appender name="SQL_LOGGER" class="ch.qos.logback.core.ConsoleAppender">
    <target>System.out</target>
    <encoder>
      <pattern>%d{yyyy/MM/dd HH:mm:ss.SSS} [%t] %highlight(%-5le) %cyan(%-40.40lo{36}) - %green(%msg) %n</pattern>
    </encoder>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>DEBUG</level>
    </filter>    
  </appender>

 <logger name="com.apri" level="DEBUG">
    <appender-ref ref="SQL_LOGGER" />
  </logger>


以上です。
よろしくお願いいたします。

(追記)
以下のようにフィルタを追加してlogback-spring.xmlの記述を変更しましたら、
フィルタは動くようになりましたが、
@AutowiredのconfigServiceがNULLとなってしまいます。

SQLLoggingFilter .java

public class SQLLoggingFilter extends Filter<ILoggingEvent> {

    @Autowired
    ConfigService configService;

    Level level;

    @Override
    public FilterReply decide(ILoggingEvent event) {
        if (event.getMessage().contains("Preparing") || event.getMessage().contains("Parameters")) {
            if(configService.isSql_log_hyouji_flg()){
                return FilterReply.NEUTRAL;
            }
            else{
                return FilterReply.DENY;
            }
        }
        else{
            return FilterReply.NEUTRAL;
        }
    }


    public void setLevel(String level) {
        this.level = Level.toLevel(level);
    }

    public void start() {
        if (this.level != null) {
            super.start();
        }
    }
}


logback-spring.xml

  <appender name="SQL_LOGGER" class="ch.qos.logback.core.ConsoleAppender">
    <target>System.out</target>
    <encoder>
      <pattern>%d{yyyy/MM/dd HH:mm:ss.SSS} [%t] %highlight(%-5le) %cyan(%-40.40lo{36}) - %green(%msg) %n</pattern>
    </encoder>
    <filter class="com.apri.common.filter.SQLLoggingFilter">
      <level>DEBUG</level>
    </filter>    
  </appender>

Filter内での@Autowiredの使用方法が分からないので、
Mapper XML内のSQLを読み込んでログに出力するサービスを作成しました。
※パラメータ部分の出力個所は、もう少し改善が必要です。

@Service
public class SQLHelperService {
  private static final Logger logger = LoggerFactory.getLogger("sql_logger");
  @Autowired
  ConfigService configService;

  public void logger_sql(String path_file_name,String mapper_id,Object params)
  throws ApplicationException {
    try{
    if(configService.isSql_log_hyouji_flg()){
          String absolute_path = new File(".").getAbsoluteFile().getParent();
       Configuration config = new Configuration();
      InputStream fileStream = new FileInputStream(absolute_path+path_file_name);
      XMLMapperBuilder parser = new XMLMapperBuilder(fileStream, config, "", config.getSqlFragments());
          parser.parse();
      MappedStatement st = config.getMappedStatement(mapper_id);
      BoundSql sql = st.getBoundSql(params);
      logger.info("[SQL]");
      logger.info(sql.getSql());
      logger.info("[Parameters]");
      if(sql.getParameterObject() != null){
        logger.info(sql.getParameterObject().toString());
          }  
         }
    }
    catch (FileNotFoundException e) {
      throw new ApplicationException(e);
    }
      }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

check解決した方法

0

以下の2つのどちらでも対応する事が出来ました。
(方法1)
TurboFilterに@Autowiredを使用した方法

CustomLoggingFilter.java

@Named("customLoggingFilter")
public class CustomLoggingFilter extends TurboFilter {

    @Autowired
    private ConfigService configService;

    @Override
    public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
        if(configService == null){
               return FilterReply.ACCEPT;
        }
           else{
               // SQLを出力する/出力しないの制御
               if(format != null){
                   if (format.contains("Preparing") || format.contains("Parameters")) {
                       if(configService.isSql_log_hyouji_flg()){
                              return FilterReply.ACCEPT;
                       }
                       else{
                              return FilterReply.DENY;
                       }
                   }
               }
            return FilterReply.ACCEPT;
           }
    }
}


ConfigService .java

@Service
@Scope("singleton")
public class ConfigService {
    // SQLのログを出力するFLG
    // true:表示、false:非表示
    private boolean sql_log_hyouji_flg = false;

    public boolean isSql_log_hyouji_flg() {
        return sql_log_hyouji_flg;
    }

    public void setSql_log_hyouji_flg(boolean sql_log_hyouji_flg) {
        this.sql_log_hyouji_flg = sql_log_hyouji_flg;
    }
}


DiscoveringPostProcessor .java

@Component
public class DiscoveringPostProcessor implements BeanPostProcessor, ApplicationContextAware {

    ApplicationContext applicationContext;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // TODO Auto-generated method stub
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        if(bean instanceof CustomLoggingFilter){
            Map<String, TurboFilter> filterBeans = applicationContext.getBeansOfType(TurboFilter.class);
            for (TurboFilter filter : filterBeans.values()) {
                LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
                for(int i = 0;i<loggerContext.getTurboFilterList().size();i++){
                    TurboFilter data =(TurboFilter)loggerContext.getTurboFilterList().get(i);
                    if(data.getClass().getName().equals(CustomLoggingFilter.class.getName())){
                        filter.setContext(data.getContext());
                        loggerContext.getTurboFilterList().remove(i);
                        loggerContext.getTurboFilterList().add(i,filter);
                    }
                }
            }
        }
        return bean;

    }


logback-spring.xml

<configuration>
  <property name="log_dir" value="C:/logs" />
  <turboFilter class="com.apri.common.filter.CustomLoggingFilter"></turboFilter>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <target>System.out</target>
    <encoder>
      <pattern>%d{yyyy/MM/dd HH:mm:ss.SSS} [%t] %highlight(%-5le) %cyan(%-40.40lo{36}) - %green(%msg) %n</pattern>
    </encoder>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>    
  </appender>


  <appender name="SQL_LOGGER" class="ch.qos.logback.core.ConsoleAppender">
    <target>System.out</target>
    <encoder>
      <pattern>%d{yyyy/MM/dd HH:mm:ss.SSS} [%t] %highlight(%-5le) %cyan(%-40.40lo{36}) - %green(%msg) %n</pattern>
    </encoder>
  <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>DEBUG</level>
    </filter>    
  </appender>

 <logger name="com.apri" level="DEBUG" additivity="false">
    <appender-ref ref="SQL_LOGGER" />
  </logger>

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


(方法2)
ログレベルの変更を使用した方法
ConfigService.java

@Service
@Scope("singleton")
public class ConfigService {

    protected final Logger logger = LoggerFactory.getLogger("com.apri");

    // SQLのログを出力するFLG
    // true:表示、false:非表示
    private boolean sql_log_hyouji_flg = false;

    public boolean isSql_log_hyouji_flg() {
        return sql_log_hyouji_flg;
    }

    public void setSql_log_hyouji_flg(boolean sql_log_hyouji_flg) {
        this.sql_log_hyouji_flg = sql_log_hyouji_flg;
        ch.qos.logback.classic.Logger log = (ch.qos.logback.classic.Logger)logger;
        if(this.sql_log_hyouji_flg){
            log.setLevel(Level.DEBUG);
        }
        else{
            log.setLevel(Level.INFO);
        }
    }


logback-spriing.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
   <!-- ファイルの出力先を指定する事。 -->
  <property name="log_dir" value="C:/logs" />
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <target>System.out</target>
    <encoder>
      <pattern>%d{yyyy/MM/dd HH:mm:ss.SSS} [%t] %highlight(%-5le) %cyan(%-40.40lo{36}) - %green(%msg) %n</pattern>
    </encoder>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>INFO</level>
    </filter>    
  </appender>

  <appender name="SQL_LOGGER" class="ch.qos.logback.core.ConsoleAppender">
    <target>System.out</target>
    <encoder>
      <pattern>%d{yyyy/MM/dd HH:mm:ss.SSS} [%t] %highlight(%-5le) %cyan(%-40.40lo{36}) - %green(%msg) %n</pattern>
    </encoder>
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
      <level>DEBUG</level>
    </filter>    
  </appender>

  <logger name="com.apri" level="DEBUG" additivity="false">
    <appender-ref ref="SQL_LOGGER" />
  </logger>

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

フィルタを実装してください

それでお望みの処理が可能になるかと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/07 15:10

    ご回答ありがとうございます。
    上記フィルタのページを確認して、
    public FilterReply decide(ILoggingEvent event)を使用して
    制御しようかと思っております。

    基本的なことが分かっておらず大変申し訳ございませんが、
    SpringbootではこのFilterをどのようにコーディングすれば処理に組み込めるのでしょうか。
    webMvcConfigファイルを作成して、以下のように登録したらエラーが発生してしましました。
    @Bean
    public FilterRegistrationBean commonFilter1() {
    FilterRegistrationBean bean = new FilterRegistrationBean();
    bean.setFilter(new SampleFilter());
    bean.setOrder(1);
    return bean;
    }

    (エラー内容)
    型 FilterRegistrationBean のメソッド setFilter(Filter) は引数 (SampleFilter) に適用できません

    キャンセル

  • 2018/04/07 23:34

    public FilterReply decide(ILoggingEvent event)ですが、
    上記の(追記)を記述する仕方でフィルタをかける事が出来ました。
    ただし、Fliter内で@Autowiredを実施して、使用したいのですがNULLとなっていしまいます。
    何か解決方法はありますでしょうか。

    キャンセル

  • 2018/04/09 08:20

    読み込み優先度の問題のことかな
    一例としてはセキュリティ設定でバズワードエンコーダーは
    コンフィグクラス→メソッドにより自己呼出
    コントロールまたはサービスクラス→Autowired

    とするようにコンフィグクラスでは自分を含むコンフィグクラスでBean指定したものは読み込めないのかと

    キャンセル

  • 2018/04/09 08:36

    あと、管理クラスでは実行されるが管理オブジェクトでは実行されないというのもあるな

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る