<commit_before>/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.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://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.aop;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.annotation.Logging;
import org.openmrs.util.OpenmrsUtil;
import org.springframework.util.StringUtils;

/**
 * This class provides the log4j aop around advice for our service layer. This advice is placed on
 * all services and daos via the spring application context. See
 * /metadata/api/spring/applicationContext.xml
 */
public class LoggingAdvice implements MethodInterceptor {
	
	/**
	 * Logger for this class. Uses the name "org.openmrs.api" so that it seems to fit into the
	 * log4j.xml configuration
	 */
	protected static final Log log = LogFactory.getLog("org.openmrs.api");
	
	/**
	 * List of all method name prefixes that result in INFO-level log messages
	 */
	private static final String[] SETTER_METHOD_PREFIXES = { "save", "create", "update", "void", "unvoid", "retire",
	        "unretire", "delete", "purge" };
	
	/**
	 * This method prints out debug statements for getters and info statements for everything else
	 * ("setters"). If debugging is turned on, execution time for each method is printed as well.
	 * This method is called for every method in the Class/Service that it is wrapped around. This
	 * method should be fairly quick and light.
	 * 
	 * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
	 */
	public Object invoke(MethodInvocation invocation) throws Throwable {
		
		Method method = invocation.getMethod();
		String name = method.getName();
		
		// decide what type of logging we're doing with the current method and loglevel
		boolean isSetterTypeOfMethod = OpenmrsUtil.stringStartsWith(name, SETTER_METHOD_PREFIXES);
		boolean logGetter = !isSetterTypeOfMethod && log.isDebugEnabled();
		boolean logSetter = isSetterTypeOfMethod && log.isInfoEnabled();
		
		// used for the execution time calculations
		long startTime = System.currentTimeMillis();
		
		// check if this method has the logging annotation on it
		Logging loggingAnnotation = null;
		if (logGetter || logSetter) {
			loggingAnnotation = method.getAnnotation(Logging.class);
			if (loggingAnnotation != null && loggingAnnotation.ignore()) {
				logGetter = false;
				logSetter = false;
			}
		}
		
		if (logGetter || logSetter) {
			StringBuilder output = new StringBuilder();
			output.append("In method ").append(method.getDeclaringClass().getSimpleName()).append(".").append(name);
			
			// print the argument values unless we're ignoring all
			if (loggingAnnotation == null || loggingAnnotation.ignoreAllArgumentValues() == false) {
				
				int x;
				Class<?>[] types = method.getParameterTypes();
				Object[] values = invocation.getArguments();
				
				// change the annotation array of indexes to a list of indexes to ignore
				List<Integer> argsToIgnore = new ArrayList<Integer>();
				if (loggingAnnotation != null && loggingAnnotation.ignoredArgumentIndexes().length > 0) {
					for (int argIndexToIgnore : loggingAnnotation.ignoredArgumentIndexes())
						argsToIgnore.add(argIndexToIgnore);
				}
				
				// loop over and print out each argument value
				output.append(". Arguments: ");
				for (x = 0; x < types.length; x++) {
					output.append(types[x].getSimpleName()).append("=");
					
					// if there is an annotation to skip this, print out a bogus string.
					if (argsToIgnore.contains(x))
						output.append("<Arg value ignored>");
					else
						output.append(values[x]);
					
					output.append(", ");
				}
				
			}
			
			// print the string as either debug or info
			if (logGetter)
				log.debug(output.toString());
			else if (logSetter)
				log.info(output.toString());
		}
		
		try {
			// do the actual method we're wrapped around
			return invocation.proceed();
		}
		catch (Throwable t) {
			if (logGetter || logSetter)
				log.error("An error occurred while executing this method. Error message: " + t.getMessage(), t);<commit_msg>TRUNK-3979: LoggingAdvice should also log which user is performing an action when an error occurs<commit_after>/**
 * The contents of this file are subject to the OpenMRS Public License
 * Version 1.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://license.openmrs.org
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * Copyright (C) OpenMRS, LLC.  All Rights Reserved.
 */
package org.openmrs.aop;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.User;
import org.openmrs.annotation.Logging;
import org.openmrs.api.context.Context;
import org.openmrs.util.OpenmrsUtil;

/**
 * This class provides the log4j aop around advice for our service layer. This advice is placed on
 * all services and daos via the spring application context. See
 * /metadata/api/spring/applicationContext.xml
 */
public class LoggingAdvice implements MethodInterceptor {
	
	/**
	 * Logger for this class. Uses the name "org.openmrs.api" so that it seems to fit into the
	 * log4j.xml configuration
	 */
	protected static final Log log = LogFactory.getLog("org.openmrs.api");
	
	/**
	 * List of all method name prefixes that result in INFO-level log messages
	 */
	private static final String[] SETTER_METHOD_PREFIXES = { "save", "create", "update", "void", "unvoid", "retire",
	        "unretire", "delete", "purge" };
	
	/**
	 * This method prints out debug statements for getters and info statements for everything else
	 * ("setters"). If debugging is turned on, execution time for each method is printed as well.
	 * This method is called for every method in the Class/Service that it is wrapped around. This
	 * method should be fairly quick and light.
	 * 
	 * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
	 */
	public Object invoke(MethodInvocation invocation) throws Throwable {
		
		Method method = invocation.getMethod();
		String name = method.getName();
		
		// decide what type of logging we're doing with the current method and loglevel
		boolean isSetterTypeOfMethod = OpenmrsUtil.stringStartsWith(name, SETTER_METHOD_PREFIXES);
		boolean logGetter = !isSetterTypeOfMethod && log.isDebugEnabled();
		boolean logSetter = isSetterTypeOfMethod && log.isInfoEnabled();
		
		// used for the execution time calculations
		long startTime = System.currentTimeMillis();
		
		// check if this method has the logging annotation on it
		Logging loggingAnnotation = null;
		if (logGetter || logSetter) {
			loggingAnnotation = method.getAnnotation(Logging.class);
			if (loggingAnnotation != null && loggingAnnotation.ignore()) {
				logGetter = false;
				logSetter = false;
			}
		}
		
		if (logGetter || logSetter) {
			StringBuilder output = new StringBuilder();
			output.append("In method ").append(method.getDeclaringClass().getSimpleName()).append(".").append(name);
			
			// print the argument values unless we're ignoring all
			if (loggingAnnotation == null || loggingAnnotation.ignoreAllArgumentValues() == false) {
				
				int x;
				Class<?>[] types = method.getParameterTypes();
				Object[] values = invocation.getArguments();
				
				// change the annotation array of indexes to a list of indexes to ignore
				List<Integer> argsToIgnore = new ArrayList<Integer>();
				if (loggingAnnotation != null && loggingAnnotation.ignoredArgumentIndexes().length > 0) {
					for (int argIndexToIgnore : loggingAnnotation.ignoredArgumentIndexes())
						argsToIgnore.add(argIndexToIgnore);
				}
				
				// loop over and print out each argument value
				output.append(". Arguments: ");
				for (x = 0; x < types.length; x++) {
					output.append(types[x].getSimpleName()).append("=");
					
					// if there is an annotation to skip this, print out a bogus string.
					if (argsToIgnore.contains(x))
						output.append("<Arg value ignored>");
					else
						output.append(values[x]);
					
					output.append(", ");
				}
				
			}
			
			// print the string as either debug or info
			if (logGetter)
				log.debug(output.toString());
			else if (logSetter)
				log.info(output.toString());
		}
		
		try {
			// do the actual method we're wrapped around
			return invocation.proceed();
		}
		catch (Throwable t) {
			if (logGetter || logSetter) {
				String username;				
				User user = Context.getAuthenticatedUser();
				if (user == null) {
					username = "Guest (Not logged in)";
				} else {
					username = user.getUsername();
					if (username == null || username.length() == 0)
						username = user.getSystemId();
				}
				log.error(String.format(
				    "An error occurred while executing this method.\nCurrent user: %s\nError message: %s", username, t
				            .getMessage()), t);
			}
{'fraction_non_alphanumeric': 0.10375075620084695, 'fraction_numerical': 0.0017140552530752167, 'mean_word_length': 3.648078725398313, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7054094', 'n_tokens_mistral': 3187, 'n_tokens_neox': 2702, 'n_words': 945}