/* * Copyright 2014 NAVER Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.navercorp.pinpoint.plugin.logback; import java.security.ProtectionDomain; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException; import com.navercorp.pinpoint.bootstrap.instrument.Instrumentor; import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformCallback; import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformTemplate; import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformTemplateAware; import com.navercorp.pinpoint.bootstrap.logging.PLogger; import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin; import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginSetupContext; /** * This modifier support slf4j 1.4.1 version and logback 0.9.8 version, or greater. * Because package name of MDC class is different on under those version * and under those version is too old. * By the way slf4j 1.4.0 version release on May 2007. * Refer to url http://mvnrepository.com/artifact/org.slf4j/slf4j-api for detail. * * @author minwoo.jung */ public class LogbackPlugin implements ProfilerPlugin, TransformTemplateAware { private final PLogger logger = PLoggerFactory.getLogger(getClass()); private TransformTemplate transformTemplate; @Override public void setup(ProfilerPluginSetupContext context) { final LogbackConfig config = new LogbackConfig(context.getConfig()); if (logger.isInfoEnabled()) { logger.info("LogbackPlugin config:{}", config); } if (!config.isLogbackLoggingTransactionInfo()) { logger.info("Logback plugin is not executed because logback transform enable config value is false."); return; } transformTemplate.transform("ch.qos.logback.classic.spi.LoggingEvent", new TransformCallback() { @Override public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { InstrumentClass mdcClass = instrumentor.getInstrumentClass(loader, "org.slf4j.MDC", null); if (mdcClass == null) { logger.warn("Can not modify. Because org.slf4j.MDC does not exist."); return null; } if (!mdcClass.hasMethod("put", "java.lang.String", "java.lang.String")) { logger.warn("Can not modify. Because put method does not exist at org.slf4j.MDC class."); return null; } if (!mdcClass.hasMethod("remove", "java.lang.String")) { logger.warn("Can not modify. Because remove method does not exist at org.slf4j.MDC class."); return null; } InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer); if (!target.hasConstructor()) { logger.warn("Can not modify. Because constructor to modify not exist at ch.qos.logback.classic.spi.LoggingEvent class." + "\nconstructor prototype : LoggingEvent();"); return null; } if (!target.hasConstructor("java.lang.String", "ch.qos.logback.classic.Logger", "ch.qos.logback.classic.Level", "java.lang.String", "java.lang.Throwable", "java.lang.Object[]")) { logger.warn("Can not modify. Because constructor to modify not exist at ch.qos.logback.classic.spi.LoggingEvent class." + "\nconstructor prototype : LoggingEvent(String fqcn, Logger logger, Level level, String message, Throwable throwable, Object[] argArray);"); return null; } target.addInterceptor("com.navercorp.pinpoint.plugin.logback.interceptor.LoggingEventOfLogbackInterceptor"); return target.toBytecode(); } }); } @Override public void setTransformTemplate(TransformTemplate transformTemplate) { this.transformTemplate = transformTemplate; } }