mirror of
https://github.com/elastic/logstash.git
synced 2025-04-24 14:47:19 -04:00
Fix: avoid gsub (frame dependent) usage from Java
`RubyString#gsub` requires a (Ruby) frame to be present. The method attempts to set a backref for the current caller's frame. When the frame stack is empty there isn't really a place to set $~. This can happen when a LogStash::Util::Loggable#logger is retrieved, from the input worker thread while not being nested in any block. Fixes #11874
This commit is contained in:
parent
1cc1ce390a
commit
ecdf8715e7
3 changed files with 56 additions and 38 deletions
|
@ -40,12 +40,21 @@ public class DeprecationLoggerExt extends RubyObject {
|
|||
super(runtime, metaClass);
|
||||
}
|
||||
|
||||
DeprecationLoggerExt(final Ruby runtime, final RubyClass metaClass, final String loggerName) {
|
||||
super(runtime, metaClass);
|
||||
initialize(loggerName);
|
||||
}
|
||||
|
||||
@JRubyMethod
|
||||
public DeprecationLoggerExt initialize(final ThreadContext context, final IRubyObject loggerName) {
|
||||
logger = new DefaultDeprecationLogger(loggerName.asJavaString());
|
||||
initialize(loggerName.asJavaString());
|
||||
return this;
|
||||
}
|
||||
|
||||
private void initialize(final String loggerName) {
|
||||
logger = new DefaultDeprecationLogger(loggerName);
|
||||
}
|
||||
|
||||
@JRubyMethod(name = "deprecated", required = 1, optional = 1)
|
||||
public IRubyObject rubyDeprecated(final ThreadContext context, final IRubyObject[] args) {
|
||||
if (args.length > 1) {
|
||||
|
|
|
@ -22,16 +22,16 @@ package org.logstash.log;
|
|||
|
||||
import org.jruby.RubyClass;
|
||||
import org.jruby.RubyModule;
|
||||
import org.jruby.RubyString;
|
||||
import org.jruby.anno.JRubyMethod;
|
||||
import org.jruby.anno.JRubyModule;
|
||||
import org.jruby.runtime.Block;
|
||||
import org.jruby.runtime.ThreadContext;
|
||||
import org.jruby.runtime.builtin.IRubyObject;
|
||||
import org.jruby.runtime.builtin.InstanceVariables;
|
||||
import org.logstash.RubyUtil;
|
||||
|
||||
import static org.logstash.RubyUtil.RUBY;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.logstash.log.SlowLoggerExt.toLong;
|
||||
|
||||
@JRubyModule(name = "Loggable")
|
||||
public final class LoggableExt {
|
||||
|
@ -64,24 +64,18 @@ public final class LoggableExt {
|
|||
return self.getSingletonClass().callMethod(context, "deprecation_logger");
|
||||
}
|
||||
|
||||
private static RubyString log4jName(final ThreadContext context, final RubyModule self) {
|
||||
IRubyObject name = self.name(context);
|
||||
if (name.isNil()) {
|
||||
final RubyClass clazz;
|
||||
private static String log4jName(final RubyModule self) {
|
||||
String name;
|
||||
if (self.getBaseName() == null) { // anonymous module/class
|
||||
RubyModule real = self;
|
||||
if (self instanceof RubyClass) {
|
||||
clazz = ((RubyClass) self).getRealClass();
|
||||
} else {
|
||||
clazz = self.getMetaClass();
|
||||
}
|
||||
name = clazz.name(context);
|
||||
if (name.isNil()) {
|
||||
name = clazz.to_s();
|
||||
real = ((RubyClass) self).getRealClass();
|
||||
}
|
||||
name = real.getName(); // for anonymous: "#<Class:0xcafebabe>"
|
||||
} else {
|
||||
name = self.getName();
|
||||
}
|
||||
return ((RubyString) ((RubyString) name).gsub(
|
||||
context, RUBY.newString("::"), RUBY.newString("."),
|
||||
Block.NULL_BLOCK
|
||||
)).downcase(context);
|
||||
return name.replace("::", ".").toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,9 +99,8 @@ public final class LoggableExt {
|
|||
}
|
||||
IRubyObject logger = instanceVariables.getInstanceVariable("logger");
|
||||
if (logger == null || logger.isNil()) {
|
||||
logger = RubyUtil.LOGGER.callMethod(context, "new",
|
||||
LoggableExt.log4jName(context, (RubyModule) self)
|
||||
);
|
||||
final String loggerName = log4jName((RubyModule) self);
|
||||
logger = RubyUtil.LOGGER.callMethod(context, "new", context.runtime.newString(loggerName));
|
||||
instanceVariables.setInstanceVariable("logger", logger);
|
||||
}
|
||||
return logger;
|
||||
|
@ -117,18 +110,15 @@ public final class LoggableExt {
|
|||
public static SlowLoggerExt slowLogger(final ThreadContext context,
|
||||
final IRubyObject self, final IRubyObject[] args) {
|
||||
final InstanceVariables instanceVariables = self.getInstanceVariables();
|
||||
SlowLoggerExt logger =
|
||||
(SlowLoggerExt) instanceVariables.getInstanceVariable("slow_logger");
|
||||
IRubyObject logger = instanceVariables.getInstanceVariable("slow_logger");
|
||||
if (logger == null || logger.isNil()) {
|
||||
logger = new SlowLoggerExt(context.runtime, RubyUtil.SLOW_LOGGER).initialize(
|
||||
context, new IRubyObject[]{
|
||||
LoggableExt.log4jName(context, (RubyModule) self), args[0], args[1],
|
||||
args[2], args[3]
|
||||
}
|
||||
final String loggerName = log4jName((RubyModule) self);
|
||||
logger = new SlowLoggerExt(context.runtime, RubyUtil.SLOW_LOGGER, loggerName,
|
||||
toLong(args[0]), toLong(args[1]), toLong(args[2]), toLong(args[3])
|
||||
);
|
||||
instanceVariables.setInstanceVariable("slow_logger", logger);
|
||||
}
|
||||
return logger;
|
||||
return (SlowLoggerExt) logger;
|
||||
}
|
||||
|
||||
@JRubyMethod(name = "deprecation_logger", meta = true)
|
||||
|
@ -141,8 +131,8 @@ public final class LoggableExt {
|
|||
}
|
||||
IRubyObject logger = instanceVariables.getInstanceVariable("deprecation_logger");
|
||||
if (logger == null || logger.isNil()) {
|
||||
logger = new DeprecationLoggerExt(context.runtime, RubyUtil.DEPRECATION_LOGGER)
|
||||
.initialize(context, LoggableExt.log4jName(context, (RubyModule) self));
|
||||
final String loggerName = log4jName((RubyModule) self);
|
||||
logger = new DeprecationLoggerExt(context.runtime, RubyUtil.DEPRECATION_LOGGER, loggerName);
|
||||
instanceVariables.setInstanceVariable("deprecation_logger", logger);
|
||||
}
|
||||
return logger;
|
||||
|
|
|
@ -55,17 +55,36 @@ public class SlowLoggerExt extends RubyObject {
|
|||
super(runtime, metaClass);
|
||||
}
|
||||
|
||||
SlowLoggerExt(final Ruby runtime, final RubyClass metaClass, final String loggerName,
|
||||
final long warnThreshold, final long infoThreshold,
|
||||
final long debugThreshold, final long traceThreshold) {
|
||||
super(runtime, metaClass);
|
||||
initialize(loggerName, warnThreshold, infoThreshold, debugThreshold, traceThreshold);
|
||||
}
|
||||
|
||||
@JRubyMethod(required = 5)
|
||||
public SlowLoggerExt initialize(final ThreadContext context, final IRubyObject[] args) {
|
||||
String loggerName = args[0].asJavaString();
|
||||
slowLogger = LogManager.getLogger("slowlog." + loggerName);
|
||||
warnThreshold = ((RubyNumeric) args[1]).getLongValue();
|
||||
infoThreshold = ((RubyNumeric) args[2]).getLongValue();
|
||||
debugThreshold = ((RubyNumeric) args[3]).getLongValue();
|
||||
traceThreshold = ((RubyNumeric) args[4]).getLongValue();
|
||||
initialize(args[0].asJavaString(), toLong(args[1]), toLong(args[2]), toLong(args[3]), toLong(args[4]));
|
||||
return this;
|
||||
}
|
||||
|
||||
private void initialize(final String loggerName,
|
||||
final long warnThreshold, final long infoThreshold,
|
||||
final long debugThreshold, final long traceThreshold) {
|
||||
slowLogger = LogManager.getLogger("slowlog." + loggerName);
|
||||
this.warnThreshold = warnThreshold;
|
||||
this.infoThreshold = infoThreshold;
|
||||
this.debugThreshold = debugThreshold;
|
||||
this.traceThreshold = traceThreshold;
|
||||
}
|
||||
|
||||
static long toLong(final IRubyObject value) {
|
||||
if (!(value instanceof RubyNumeric)) {
|
||||
throw RubyUtil.RUBY.newTypeError("Numeric expected, got " + value.getMetaClass());
|
||||
}
|
||||
return ((RubyNumeric) value).getLongValue();
|
||||
}
|
||||
|
||||
private RubyHash asData(final ThreadContext context, final IRubyObject pluginParams,
|
||||
final IRubyObject event, final IRubyObject durationNanos) {
|
||||
RubyHash data = RubyHash.newHash(context.runtime);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue