diff options
Diffstat (limited to 'client/go/cmd')
-rw-r--r-- | client/go/cmd/logfmt/handleline.go | 116 | ||||
-rw-r--r-- | client/go/cmd/logfmt/internal.go | 106 | ||||
-rw-r--r-- | client/go/cmd/logfmt/internal_names.txt | 782 | ||||
-rw-r--r-- | client/go/cmd/logfmt/internal_notnames.txt | 8 | ||||
-rw-r--r-- | client/go/cmd/logfmt/internal_test.go | 34 | ||||
-rw-r--r-- | client/go/cmd/logfmt/levelflags.go | 72 | ||||
-rw-r--r-- | client/go/cmd/logfmt/levelflags_test.go | 74 | ||||
-rw-r--r-- | client/go/cmd/logfmt/options.go | 47 | ||||
-rw-r--r-- | client/go/cmd/logfmt/plusminusflag.go | 67 | ||||
-rw-r--r-- | client/go/cmd/logfmt/regexflag.go | 38 | ||||
-rw-r--r-- | client/go/cmd/logfmt/regexflag_test.go | 41 | ||||
-rw-r--r-- | client/go/cmd/logfmt/runlogfmt.go | 78 | ||||
-rw-r--r-- | client/go/cmd/logfmt/showflags.go | 76 | ||||
-rw-r--r-- | client/go/cmd/logfmt/showflags_test.go | 61 | ||||
-rw-r--r-- | client/go/cmd/logfmt/tail.go | 156 |
15 files changed, 1756 insertions, 0 deletions
diff --git a/client/go/cmd/logfmt/handleline.go b/client/go/cmd/logfmt/handleline.go new file mode 100644 index 00000000000..33a1a1b386b --- /dev/null +++ b/client/go/cmd/logfmt/handleline.go @@ -0,0 +1,116 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "fmt" + "strconv" + "strings" + "time" +) + +// handle a line in "vespa.log" format; do filtering and formatting as specified in opts + +func handleLine(opts *Options, line string) (output string, err error) { + fields := strings.SplitN(line, "\t", 7) + if len(fields) < 7 { + return "", fmt.Errorf("not enough fields: '%s'", line) + } + timestampfield := fields[0] // seconds, optional fractional seconds + hostfield := fields[1] + pidfield := fields[2] // pid, optional tid + servicefield := fields[3] + componentfield := fields[4] + levelfield := fields[5] + messagefields := fields[6:] + + if !opts.showLevel(levelfield) { + return "", nil + } + if opts.OnlyHostname != "" && opts.OnlyHostname != hostfield { + return "", nil + } + if opts.OnlyPid != "" && opts.OnlyPid != pidfield { + return "", nil + } + if opts.OnlyService != "" && opts.OnlyService != servicefield { + return "", nil + } + if opts.OnlyInternal && !isInternal(componentfield) { + return "", nil + } + if opts.ComponentFilter.unmatched(componentfield) { + return "", nil + } + if opts.MessageFilter.unmatched(strings.Join(messagefields, "\t")) { + return "", nil + } + + var buf strings.Builder + + if opts.showField("fmttime") { + secs, err := strconv.ParseFloat(timestampfield, 64) + if err != nil { + return "", err + } + nsecs := int64(secs * 1e9) + timestamp := time.Unix(0, nsecs) + if opts.showField("usecs") { + buf.WriteString(timestamp.Format("[2006-01-02 15:04:05.000000] ")) + } else if opts.showField("msecs") { + buf.WriteString(timestamp.Format("[2006-01-02 15:04:05.000] ")) + } else { + buf.WriteString(timestamp.Format("[2006-01-02 15:04:05] ")) + } + } else if opts.showField("time") { + buf.WriteString(timestampfield) + buf.WriteString(" ") + } + if opts.showField("host") { + buf.WriteString(fmt.Sprintf("%-8s ", hostfield)) + } + if opts.showField("level") { + buf.WriteString(fmt.Sprintf("%-7s ", strings.ToUpper(levelfield))) + } + if opts.showField("pid") { + // OnlyPid, _, _ := strings.Cut(pidfield, "/") + buf.WriteString(fmt.Sprintf("%6s ", pidfield)) + } + if opts.showField("service") { + if opts.TruncateService { + buf.WriteString(fmt.Sprintf("%-9.9s ", servicefield)) + } else { + buf.WriteString(fmt.Sprintf("%-16s ", servicefield)) + } + } + if opts.showField("component") { + if opts.TruncateComponent { + buf.WriteString(fmt.Sprintf("%-15.15s ", componentfield)) + } else { + buf.WriteString(fmt.Sprintf("%s\t", componentfield)) + } + } + if opts.showField("message") { + var msgBuf strings.Builder + for idx, message := range messagefields { + if idx > 0 { + msgBuf.WriteString("\n\t") + } + if opts.DequoteNewlines { + message = strings.ReplaceAll(message, "\\n\\t", "\n\t") + message = strings.ReplaceAll(message, "\\n", "\n\t") + } + msgBuf.WriteString(message) + } + message := msgBuf.String() + if strings.Contains(message, "\n") { + buf.WriteString("\n\t") + } + buf.WriteString(message) + } + buf.WriteString("\n") + output = buf.String() + return +} diff --git a/client/go/cmd/logfmt/internal.go b/client/go/cmd/logfmt/internal.go new file mode 100644 index 00000000000..992c537f939 --- /dev/null +++ b/client/go/cmd/logfmt/internal.go @@ -0,0 +1,106 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "strings" +) + +// is componentName a vespa-internal name? + +func isInternal(componentName string) bool { + cs := strings.Split(componentName, ".") + if len(cs) == 0 || cs[0] != "Container" { + return true + } + if len(cs) < 3 { + return false + } + if cs[1] == "ai" && cs[2] == "vespa" { + return true + } + if cs[1] == "com" && cs[2] == "yahoo" && len(cs) > 3 { + return internalComYahooNames[cs[3]] + } + return false +} + +// a constant: +var internalComYahooNames = map[string]bool{ + "abicheck": true, + "api": true, + "application": true, + "binaryprefix": true, + "clientmetrics": true, + "cloud": true, + "collections": true, + "component": true, + "compress": true, + "concurrent": true, + "configtest": true, + "config": true, + "container": true, + "data": true, + "docprocs": true, + "docproc": true, + "documentapi": true, + "documentmodel": true, + "document": true, + "dummyreceiver": true, + "embedding": true, + "errorhandling": true, + "exception": true, + "feedapi": true, + "feedhandler": true, + "filedistribution": true, + "fs4": true, + "fsa": true, + "geo": true, + "io": true, + "javacc": true, + "jdisc": true, + "jrt": true, + "lang": true, + "language": true, + "logserver": true, + "log": true, + "messagebus": true, + "metrics": true, + "nativec": true, + "net": true, + "osgi": true, + "path": true, + "plugin": true, + "prelude": true, + "processing": true, + "protect": true, + "reflection": true, + "restapi": true, + "schema": true, + "searchdefinition": true, + "searchlib": true, + "search": true, + "security": true, + "slime": true, + "socket": true, + "statistics": true, + "stream": true, + "system": true, + "tensor": true, + "test": true, + "text": true, + "time": true, + "transaction": true, + "vdslib": true, + "vespaclient": true, + "vespafeeder": true, + "vespaget": true, + "vespastat": true, + "vespasummarybenchmark": true, + "vespa": true, + "vespavisit": true, + "vespaxmlparser": true, + "yolean": true, +} diff --git a/client/go/cmd/logfmt/internal_names.txt b/client/go/cmd/logfmt/internal_names.txt new file mode 100644 index 00000000000..cc554546fcc --- /dev/null +++ b/client/go/cmd/logfmt/internal_names.txt @@ -0,0 +1,782 @@ +sentinel.sentinel.config +searchnode.eval.Test +Container.ai.vespa.client.dsl.Test +Container.ai.vespa.cloud.Test +Container.ai.vespa.embedding.Test +Container.ai.vespa.explicitversion.Test +Container.ai.vespa.explicitversion_dep.Test +Container.ai.vespa.feed.client.Test +Container.ai.vespa.feed.client.impl.Test +Container.ai.vespa.hosted.api.Test +Container.ai.vespa.hosted.cd.Test +Container.ai.vespa.hosted.cd.cloud.impl.Test +Container.ai.vespa.hosted.cd.commons.Test +Container.ai.vespa.hosted.cd.internal.Test +Container.ai.vespa.hosted.client.Test +Container.ai.vespa.hosted.plugin.Test +Container.ai.vespa.http.Test +Container.ai.vespa.intellij.schema.Test +Container.ai.vespa.intellij.schema.findUsages.Test +Container.ai.vespa.intellij.schema.hierarchy.Test +Container.ai.vespa.intellij.schema.lexer.Test +Container.ai.vespa.intellij.schema.model.Test +Container.ai.vespa.intellij.schema.parser.Test +Container.ai.vespa.intellij.schema.psi.Test +Container.ai.vespa.intellij.schema.psi.impl.Test +Container.ai.vespa.intellij.schema.structure.Test +Container.ai.vespa.intellij.schema.utils.Test +Container.ai.vespa.logserver.protocol.Test +Container.ai.vespa.metricsproxy.core.Test +Container.ai.vespa.metricsproxy.http.Test +Container.ai.vespa.metricsproxy.http.application.Test +Container.ai.vespa.metricsproxy.http.metrics.Test +Container.ai.vespa.metricsproxy.http.prometheus.Test +Container.ai.vespa.metricsproxy.http.yamas.Test +Container.ai.vespa.metricsproxy.metric.Test +Container.ai.vespa.metricsproxy.metric.dimensions.Test +Container.ai.vespa.metricsproxy.metric.model.Test +Container.ai.vespa.metricsproxy.metric.model.json.Test +Container.ai.vespa.metricsproxy.metric.model.processing.Test +Container.ai.vespa.metricsproxy.metric.model.prometheus.Test +Container.ai.vespa.metricsproxy.node.Test +Container.ai.vespa.metricsproxy.rpc.Test +Container.ai.vespa.metricsproxy.service.Test +Container.ai.vespa.metricsproxy.telegraf.Test +Container.ai.vespa.modelintegration.evaluator.Test +Container.ai.vespa.models.evaluation.Test +Container.ai.vespa.models.handler.Test +Container.ai.vespa.noversion.Test +Container.ai.vespa.noversion_dep.Test +Container.ai.vespa.rankingexpression.importer.Test +Container.ai.vespa.rankingexpression.importer.configmodelview.Test +Container.ai.vespa.rankingexpression.importer.lightgbm.Test +Container.ai.vespa.rankingexpression.importer.onnx.Test +Container.ai.vespa.rankingexpression.importer.operations.Test +Container.ai.vespa.rankingexpression.importer.tensorflow.Test +Container.ai.vespa.rankingexpression.importer.vespa.Test +Container.ai.vespa.rankingexpression.importer.vespa.parser.Test +Container.ai.vespa.rankingexpression.importer.xgboost.Test +Container.ai.vespa.reindexing.Test +Container.ai.vespa.reindexing.http.Test +Container.ai.vespa.searchlib.searchprotocol.protobuf.Test +Container.ai.vespa.util.http.hc4.Test +Container.ai.vespa.util.http.hc4.retry.Test +Container.ai.vespa.util.http.hc5.Test +Container.ai.vespa.validation.Test +Container.com.yahoo.abicheck.classtree.Test +Container.com.yahoo.abicheck.collector.Test +Container.com.yahoo.abicheck.mojo.Test +Container.com.yahoo.abicheck.setmatcher.Test +Container.com.yahoo.abicheck.signature.Test +Container.com.yahoo.api.annotations.Test +Container.com.yahoo.application.Test +Container.com.yahoo.application.container.Test +Container.com.yahoo.application.container.handler.Test +Container.com.yahoo.application.container.impl.Test +Container.com.yahoo.application.content.Test +Container.com.yahoo.application.preprocessor.Test +Container.com.yahoo.binaryprefix.Test +Container.com.yahoo.clientmetrics.Test +Container.com.yahoo.cloud.config.Test +Container.com.yahoo.collections.Test +Container.com.yahoo.component.Test +Container.com.yahoo.component.annotation.Test +Container.com.yahoo.component.chain.Test +Container.com.yahoo.component.chain.dependencies.Test +Container.com.yahoo.component.chain.dependencies.ordering.Test +Container.com.yahoo.component.chain.model.Test +Container.com.yahoo.component.provider.Test +Container.com.yahoo.compress.Test +Container.com.yahoo.concurrent.Test +Container.com.yahoo.concurrent.classlock.Test +Container.com.yahoo.concurrent.maintenance.Test +Container.com.yahoo.config.Test +Container.com.yahoo.config.application.Test +Container.com.yahoo.config.application.api.Test +Container.com.yahoo.config.application.api.xml.Test +Container.com.yahoo.config.codegen.Test +Container.com.yahoo.config.docproc.Test +Container.com.yahoo.config.ini.Test +Container.com.yahoo.config.model.Test +Container.com.yahoo.config.model.admin.Test +Container.com.yahoo.config.model.api.Test +Container.com.yahoo.config.model.api.container.Test +Container.com.yahoo.config.model.application.Test +Container.com.yahoo.config.model.application.provider.Test +Container.com.yahoo.config.model.builder.xml.Test +Container.com.yahoo.config.model.deploy.Test +Container.com.yahoo.config.model.graph.Test +Container.com.yahoo.config.model.producer.Test +Container.com.yahoo.config.model.provision.Test +Container.com.yahoo.config.model.test.Test +Container.com.yahoo.config.provision.Test +Container.com.yahoo.config.provision.exception.Test +Container.com.yahoo.config.provision.host.Test +Container.com.yahoo.config.provisioning.Test +Container.com.yahoo.config.provision.security.Test +Container.com.yahoo.config.provision.serialization.Test +Container.com.yahoo.config.provision.zone.Test +Container.com.yahoo.config.subscription.Test +Container.com.yahoo.config.subscription.impl.Test +Container.com.yahoo.configtest.Test +Container.com.yahoo.config.text.Test +Container.com.yahoo.container.Test +Container.com.yahoo.container.bundle.Test +Container.com.yahoo.container.core.Test +Container.com.yahoo.container.core.config.Test +Container.com.yahoo.container.core.config.testutil.Test +Container.com.yahoo.container.core.document.Test +Container.com.yahoo.container.core.documentapi.Test +Container.com.yahoo.container.core.http.Test +Container.com.yahoo.container.core.identity.Test +Container.com.yahoo.container.di.Test +Container.com.yahoo.container.di.componentgraph.Test +Container.com.yahoo.container.di.componentgraph.core.Test +Container.com.yahoo.container.di.componentgraph.cycle.Test +Container.com.yahoo.container.di.config.Test +Container.com.yahoo.container.handler.Test +Container.com.yahoo.container.handler.metrics.Test +Container.com.yahoo.container.handler.observability.Test +Container.com.yahoo.container.handler.test.Test +Container.com.yahoo.container.handler.threadpool.Test +Container.com.yahoo.container.http.Test +Container.com.yahoo.container.http.filter.Test +Container.com.yahoo.container.jdisc.Test +Container.com.yahoo.container.jdisc.athenz.Test +Container.com.yahoo.container.jdisc.component.Test +Container.com.yahoo.container.jdisc.config.Test +Container.com.yahoo.container.jdisc.messagebus.Test +Container.com.yahoo.container.jdisc.metric.Test +Container.com.yahoo.container.jdisc.metric.state.Test +Container.com.yahoo.container.jdisc.secretstore.Test +Container.com.yahoo.container.jdisc.state.Test +Container.com.yahoo.container.jdisc.utils.Test +Container.com.yahoo.container.logging.Test +Container.com.yahoo.container.plugin.bundle.Test +Container.com.yahoo.container.plugin.classanalysis.Test +Container.com.yahoo.container.plugin.mojo.Test +Container.com.yahoo.container.plugin.osgi.Test +Container.com.yahoo.container.plugin.util.Test +Container.com.yahoo.container.protect.Test +Container.com.yahoo.container.standalone.Test +Container.com.yahoo.container.usability.Test +Container.com.yahoo.data.Test +Container.com.yahoo.data.access.Test +Container.com.yahoo.data.access.simple.Test +Container.com.yahoo.data.access.slime.Test +Container.com.yahoo.docproc.Test +Container.com.yahoo.docproc.impl.Test +Container.com.yahoo.docproc.jdisc.Test +Container.com.yahoo.docproc.jdisc.messagebus.Test +Container.com.yahoo.docproc.jdisc.metric.Test +Container.com.yahoo.docproc.jdisc.observability.Test +Container.com.yahoo.docproc.proxy.Test +Container.com.yahoo.docprocs.indexing.Test +Container.com.yahoo.document.Test +Container.com.yahoo.document.annotation.Test +Container.com.yahoo.documentapi.Test +Container.com.yahoo.documentapi.local.Test +Container.com.yahoo.documentapi.messagebus.Test +Container.com.yahoo.documentapi.messagebus.protocol.Test +Container.com.yahoo.documentapi.messagebus.systemstate.rule.Test +Container.com.yahoo.documentapi.metrics.Test +Container.com.yahoo.document.config.Test +Container.com.yahoo.document.datatypes.Test +Container.com.yahoo.document.fieldpathupdate.Test +Container.com.yahoo.document.fieldset.Test +Container.com.yahoo.document.idstring.Test +Container.com.yahoo.document.internal.Test +Container.com.yahoo.document.json.Test +Container.com.yahoo.document.json.document.Test +Container.com.yahoo.document.json.readers.Test +Container.com.yahoo.documentmodel.Test +Container.com.yahoo.document.predicate.Test +Container.com.yahoo.document.restapi.resource.Test +Container.com.yahoo.document.select.Test +Container.com.yahoo.document.select.convert.Test +Container.com.yahoo.document.select.parser.Test +Container.com.yahoo.document.select.rule.Test +Container.com.yahoo.document.select.simple.Test +Container.com.yahoo.document.serialization.Test +Container.com.yahoo.document.update.Test +Container.com.yahoo.dummyreceiver.Test +Container.com.yahoo.embedding.Test +Container.com.yahoo.errorhandling.Test +Container.com.yahoo.exception.Test +Container.com.yahoo.feedapi.Test +Container.com.yahoo.feedhandler.Test +Container.com.yahoo.filedistribution.fileacquirer.Test +Container.com.yahoo.fs4.Test +Container.com.yahoo.fsa.Test +Container.com.yahoo.fsa.conceptnet.Test +Container.com.yahoo.fsa.segmenter.Test +Container.com.yahoo.fsa.topicpredictor.Test +Container.com.yahoo.geo.Test +Container.com.yahoo.io.Test +Container.com.yahoo.io.reader.Test +Container.com.yahoo.javacc.Test +Container.com.yahoo.jdisc.Test +Container.com.yahoo.jdisc.application.Test +Container.com.yahoo.jdisc.bundle.Test +Container.com.yahoo.jdisc.bundle.a.Test +Container.com.yahoo.jdisc.bundle.b.Test +Container.com.yahoo.jdisc.bundle.c.Test +Container.com.yahoo.jdisc.bundle.d.Test +Container.com.yahoo.jdisc.bundle.e.Test +Container.com.yahoo.jdisc.bundle.f.Test +Container.com.yahoo.jdisc.bundle.g.Test +Container.com.yahoo.jdisc.bundle.g_act.Test +Container.com.yahoo.jdisc.bundle.h.Test +Container.com.yahoo.jdisc.bundle.i.Test +Container.com.yahoo.jdisc.bundle.j.Test +Container.com.yahoo.jdisc.bundle.k.Test +Container.com.yahoo.jdisc.bundle.l.Test +Container.com.yahoo.jdisc.bundle.m.Test +Container.com.yahoo.jdisc.bundle.my_act.Test +Container.com.yahoo.jdisc.bundle.n.Test +Container.com.yahoo.jdisc.bundle.o.Test +Container.com.yahoo.jdisc.bundle.p.Test +Container.com.yahoo.jdisc.bundle.q.Test +Container.com.yahoo.jdisc.bundle.r.Test +Container.com.yahoo.jdisc.bundle.s.Test +Container.com.yahoo.jdisc.bundle.t.Test +Container.com.yahoo.jdisc.bundle.u.Test +Container.com.yahoo.jdisc.client.Test +Container.com.yahoo.jdisc.cloud.aws.Test +Container.com.yahoo.jdisc.core.Test +Container.com.yahoo.jdisc.handler.Test +Container.com.yahoo.jdisc.http.Test +Container.com.yahoo.jdisc.http.cloud.Test +Container.com.yahoo.jdisc.http.filter.Test +Container.com.yahoo.jdisc.http.filter.chain.Test +Container.com.yahoo.jdisc.http.filter.security.athenz.Test +Container.com.yahoo.jdisc.http.filter.security.base.Test +Container.com.yahoo.jdisc.http.filter.security.cors.Test +Container.com.yahoo.jdisc.http.filter.security.csp.Test +Container.com.yahoo.jdisc.http.filter.security.misc.Test +Container.com.yahoo.jdisc.http.filter.security.rule.Test +Container.com.yahoo.jdisc.http.filter.util.Test +Container.com.yahoo.jdisc.http.server.jetty.Test +Container.com.yahoo.jdisc.http.server.jetty.testutils.Test +Container.com.yahoo.jdisc.http.ssl.impl.Test +Container.com.yahoo.jdisc.metrics.yamasconsumer.cloud.Test +Container.com.yahoo.jdisc.refcount.Test +Container.com.yahoo.jdisc.service.Test +Container.com.yahoo.jdisc.statistics.Test +Container.com.yahoo.jdisc.test.Test +Container.com.yahoo.jrt.Test +Container.com.yahoo.jrt.slobrok.Test +Container.com.yahoo.jrt.slobrok.api.Test +Container.com.yahoo.jrt.slobrok.server.Test +Container.com.yahoo.jrt.tool.Test +Container.com.yahoo.lang.Test +Container.com.yahoo.language.Test +Container.com.yahoo.language.detect.Test +Container.com.yahoo.language.opennlp.Test +Container.com.yahoo.language.process.Test +Container.com.yahoo.language.provider.Test +Container.com.yahoo.language.sentencepiece.Test +Container.com.yahoo.language.simple.Test +Container.com.yahoo.language.simple.kstem.Test +Container.com.yahoo.language.tools.Test +Container.com.yahoo.language.wordpiece.Test +Container.com.yahoo.log.Test +Container.com.yahoo.log.event.Test +Container.com.yahoo.log.impl.Test +Container.com.yahoo.logserver.Test +Container.com.yahoo.logserver.filter.Test +Container.com.yahoo.logserver.handlers.Test +Container.com.yahoo.logserver.handlers.archive.Test +Container.com.yahoo.logserver.handlers.logmetrics.Test +Container.com.yahoo.logserver.testutils.Test +Container.com.yahoo.messagebus.Test +Container.com.yahoo.messagebus.jdisc.Test +Container.com.yahoo.messagebus.jdisc.test.Test +Container.com.yahoo.messagebus.network.Test +Container.com.yahoo.messagebus.network.local.Test +Container.com.yahoo.messagebus.network.rpc.Test +Container.com.yahoo.messagebus.network.rpc.test.Test +Container.com.yahoo.messagebus.routing.Test +Container.com.yahoo.messagebus.routing.test.Test +Container.com.yahoo.messagebus.shared.Test +Container.com.yahoo.messagebus.test.Test +Container.com.yahoo.metrics.Test +Container.com.yahoo.metrics.simple.Test +Container.com.yahoo.metrics.simple.jdisc.Test +Container.com.yahoo.metrics.simple.runtime.Test +Container.com.yahoo.nativec.Test +Container.com.yahoo.net.Test +Container.com.yahoo.osgi.Test +Container.com.yahoo.osgi.annotation.Test +Container.com.yahoo.osgi.provider.model.Test +Container.com.yahoo.path.Test +Container.com.yahoo.plugin.Test +Container.com.yahoo.prelude.Test +Container.com.yahoo.prelude.cluster.Test +Container.com.yahoo.prelude.fastsearch.Test +Container.com.yahoo.prelude.hitfield.Test +Container.com.yahoo.prelude.query.Test +Container.com.yahoo.prelude.query.parser.Test +Container.com.yahoo.prelude.query.textualrepresentation.Test +Container.com.yahoo.prelude.querytransform.Test +Container.com.yahoo.prelude.searcher.Test +Container.com.yahoo.prelude.semantics.Test +Container.com.yahoo.prelude.semantics.benchmark.Test +Container.com.yahoo.prelude.semantics.config.Test +Container.com.yahoo.prelude.semantics.engine.Test +Container.com.yahoo.prelude.semantics.parser.Test +Container.com.yahoo.prelude.semantics.rule.Test +Container.com.yahoo.prelude.statistics.Test +Container.com.yahoo.processing.Test +Container.com.yahoo.processing.execution.Test +Container.com.yahoo.processing.execution.chain.Test +Container.com.yahoo.processing.handler.Test +Container.com.yahoo.processing.impl.Test +Container.com.yahoo.processing.processors.Test +Container.com.yahoo.processing.rendering.Test +Container.com.yahoo.processing.request.Test +Container.com.yahoo.processing.request.properties.Test +Container.com.yahoo.processing.response.Test +Container.com.yahoo.processing.test.Test +Container.com.yahoo.protect.Test +Container.com.yahoo.reflection.Test +Container.com.yahoo.restapi.Test +Container.com.yahoo.schema.Test +Container.com.yahoo.schema.derived.Test +Container.com.yahoo.schema.derived.validation.Test +Container.com.yahoo.schema.document.Test +Container.com.yahoo.schema.document.annotation.Test +Container.com.yahoo.schema.expressiontransforms.Test +Container.com.yahoo.schema.fieldoperation.Test +Container.com.yahoo.schema.parser.Test +Container.com.yahoo.schema.processing.Test +Container.com.yahoo.schema.processing.multifieldresolver.Test +Container.com.yahoo.search.Test +Container.com.yahoo.search.cluster.Test +Container.com.yahoo.search.config.Test +Container.com.yahoo.search.dispatch.Test +Container.com.yahoo.search.dispatch.rpc.Test +Container.com.yahoo.search.dispatch.searchcluster.Test +Container.com.yahoo.search.federation.Test +Container.com.yahoo.search.federation.selection.Test +Container.com.yahoo.search.federation.sourceref.Test +Container.com.yahoo.search.grouping.Test +Container.com.yahoo.search.grouping.request.Test +Container.com.yahoo.search.grouping.request.parser.Test +Container.com.yahoo.search.grouping.result.Test +Container.com.yahoo.search.grouping.vespa.Test +Container.com.yahoo.search.handler.Test +Container.com.yahoo.search.handler.observability.Test +Container.com.yahoo.search.intent.model.Test +Container.com.yahoo.searchlib.Test +Container.com.yahoo.searchlib.aggregation.Test +Container.com.yahoo.searchlib.aggregation.hll.Test +Container.com.yahoo.searchlib.document.Test +Container.com.yahoo.searchlib.expression.Test +Container.com.yahoo.searchlib.gbdt.Test +Container.com.yahoo.searchlib.rankingexpression.Test +Container.com.yahoo.searchlib.rankingexpression.evaluation.Test +Container.com.yahoo.searchlib.rankingexpression.evaluation.gbdtoptimization.Test +Container.com.yahoo.searchlib.rankingexpression.evaluation.tensoroptimization.Test +Container.com.yahoo.searchlib.rankingexpression.parser.Test +Container.com.yahoo.searchlib.rankingexpression.rule.Test +Container.com.yahoo.searchlib.rankingexpression.transform.Test +Container.com.yahoo.searchlib.ranking.features.Test +Container.com.yahoo.searchlib.ranking.features.fieldmatch.Test +Container.com.yahoo.searchlib.tensor.Test +Container.com.yahoo.searchlib.treenet.Test +Container.com.yahoo.searchlib.treenet.parser.Test +Container.com.yahoo.searchlib.treenet.rule.Test +Container.com.yahoo.search.match.Test +Container.com.yahoo.search.pagetemplates.Test +Container.com.yahoo.search.pagetemplates.config.Test +Container.com.yahoo.search.pagetemplates.engine.Test +Container.com.yahoo.search.pagetemplates.engine.resolvers.Test +Container.com.yahoo.search.pagetemplates.model.Test +Container.com.yahoo.search.pagetemplates.result.Test +Container.com.yahoo.search.predicate.Test +Container.com.yahoo.search.predicate.annotator.Test +Container.com.yahoo.search.predicate.benchmarks.Test +Container.com.yahoo.search.predicate.index.Test +Container.com.yahoo.search.predicate.index.conjunction.Test +Container.com.yahoo.search.predicate.optimization.Test +Container.com.yahoo.search.predicate.serialization.Test +Container.com.yahoo.search.predicate.utils.Test +Container.com.yahoo.search.query.Test +Container.com.yahoo.search.query.context.Test +Container.com.yahoo.search.query.gui.Test +Container.com.yahoo.search.query.parser.Test +Container.com.yahoo.search.query.profile.Test +Container.com.yahoo.search.query.profile.compiled.Test +Container.com.yahoo.search.query.profile.config.Test +Container.com.yahoo.search.query.profile.types.Test +Container.com.yahoo.search.query.properties.Test +Container.com.yahoo.search.query.ranking.Test +Container.com.yahoo.search.query.restapi.Test +Container.com.yahoo.search.query.rewrite.Test +Container.com.yahoo.search.query.rewrite.rewriters.Test +Container.com.yahoo.search.query.textserialize.Test +Container.com.yahoo.search.query.textserialize.item.Test +Container.com.yahoo.search.query.textserialize.parser.Test +Container.com.yahoo.search.query.textserialize.serializer.Test +Container.com.yahoo.search.querytransform.Test +Container.com.yahoo.search.rendering.Test +Container.com.yahoo.search.result.Test +Container.com.yahoo.search.schema.Test +Container.com.yahoo.search.schema.internal.Test +Container.com.yahoo.search.searchchain.Test +Container.com.yahoo.search.searchchain.example.Test +Container.com.yahoo.search.searchchain.model.Test +Container.com.yahoo.search.searchchain.model.federation.Test +Container.com.yahoo.search.searchchain.testutil.Test +Container.com.yahoo.search.searchers.Test +Container.com.yahoo.search.statistics.Test +Container.com.yahoo.search.yql.Test +Container.com.yahoo.security.Test +Container.com.yahoo.security.tls.Test +Container.com.yahoo.slime.Test +Container.com.yahoo.socket.test.Test +Container.com.yahoo.stream.Test +Container.com.yahoo.system.Test +Container.com.yahoo.system.execution.Test +Container.com.yahoo.tensor.Test +Container.com.yahoo.tensor.evaluation.Test +Container.com.yahoo.tensor.functions.Test +Container.com.yahoo.tensor.serialization.Test +Container.com.yahoo.test.Test +Container.com.yahoo.test.json.Test +Container.com.yahoo.text.Test +Container.com.yahoo.text.internal.Test +Container.com.yahoo.text.interpretation.Test +Container.com.yahoo.time.Test +Container.com.yahoo.transaction.Test +Container.com.yahoo.vdslib.Test +Container.com.yahoo.vdslib.distribution.Test +Container.com.yahoo.vdslib.state.Test +Container.com.yahoo.vespa.Test +Container.com.yahoo.vespa.applicationmodel.Test +Container.com.yahoo.vespa.athenz.api.Test +Container.com.yahoo.vespa.athenz.aws.Test +Container.com.yahoo.vespa.athenz.client.Test +Container.com.yahoo.vespa.athenz.client.common.Test +Container.com.yahoo.vespa.athenz.client.common.bindings.Test +Container.com.yahoo.vespa.athenz.client.common.serializers.Test +Container.com.yahoo.vespa.athenz.client.zms.Test +Container.com.yahoo.vespa.athenz.client.zms.bindings.Test +Container.com.yahoo.vespa.athenz.client.zts.Test +Container.com.yahoo.vespa.athenz.client.zts.bindings.Test +Container.com.yahoo.vespa.athenz.client.zts.utils.Test +Container.com.yahoo.vespa.athenz.identity.Test +Container.com.yahoo.vespa.athenz.identityprovider.api.Test +Container.com.yahoo.vespa.athenz.identityprovider.api.bindings.Test +Container.com.yahoo.vespa.athenz.identityprovider.client.Test +Container.com.yahoo.vespa.athenz.tls.Test +Container.com.yahoo.vespa.athenz.utils.Test +Container.com.yahoo.vespa.athenz.zpe.Test +Container.com.yahoo.vespaclient.Test +Container.com.yahoo.vespa.clustercontroller.apps.clustercontroller.Test +Container.com.yahoo.vespa.clustercontroller.apputil.communication.http.Test +Container.com.yahoo.vespa.clustercontroller.core.Test +Container.com.yahoo.vespa.clustercontroller.core.database.Test +Container.com.yahoo.vespa.clustercontroller.core.hostinfo.Test +Container.com.yahoo.vespa.clustercontroller.core.listeners.Test +Container.com.yahoo.vespa.clustercontroller.core.restapiv2.Test +Container.com.yahoo.vespa.clustercontroller.core.restapiv2.requests.Test +Container.com.yahoo.vespa.clustercontroller.core.rpc.Test +Container.com.yahoo.vespa.clustercontroller.core.status.Test +Container.com.yahoo.vespa.clustercontroller.core.status.statuspage.Test +Container.com.yahoo.vespa.clustercontroller.utils.communication.async.Test +Container.com.yahoo.vespa.clustercontroller.utils.communication.http.Test +Container.com.yahoo.vespa.clustercontroller.utils.communication.http.writer.Test +Container.com.yahoo.vespa.clustercontroller.utils.staterestapi.Test +Container.com.yahoo.vespa.clustercontroller.utils.staterestapi.errors.Test +Container.com.yahoo.vespa.clustercontroller.utils.staterestapi.requests.Test +Container.com.yahoo.vespa.clustercontroller.utils.staterestapi.response.Test +Container.com.yahoo.vespa.clustercontroller.utils.staterestapi.server.Test +Container.com.yahoo.vespa.clustercontroller.utils.util.Test +Container.com.yahoo.vespa.config.Test +Container.com.yahoo.vespa.config.benchmark.Test +Container.com.yahoo.vespa.config.buildergen.Test +Container.com.yahoo.vespa.config.content.Test +Container.com.yahoo.vespa.config.content.core.Test +Container.com.yahoo.vespa.config.content.reindexing.Test +Container.com.yahoo.vespa.config.core.Test +Container.com.yahoo.vespa.configdefinition.Test +Container.com.yahoo.vespa.configmodel.producers.Test +Container.com.yahoo.vespa.config.parser.Test +Container.com.yahoo.vespa.config.protocol.Test +Container.com.yahoo.vespa.config.proxy.Test +Container.com.yahoo.vespa.config.proxy.filedistribution.Test +Container.com.yahoo.vespa.config.search.Test +Container.com.yahoo.vespa.config.search.core.Test +Container.com.yahoo.vespa.config.server.Test +Container.com.yahoo.vespa.config.server.application.Test +Container.com.yahoo.vespa.config.server.configchange.Test +Container.com.yahoo.vespa.config.server.deploy.Test +Container.com.yahoo.vespa.config.server.filedistribution.Test +Container.com.yahoo.vespa.configserver.flags.Test +Container.com.yahoo.vespa.configserver.flags.db.Test +Container.com.yahoo.vespa.configserver.flags.http.Test +Container.com.yahoo.vespa.config.server.host.Test +Container.com.yahoo.vespa.config.server.http.Test +Container.com.yahoo.vespa.config.server.http.status.Test +Container.com.yahoo.vespa.config.server.http.v1.Test +Container.com.yahoo.vespa.config.server.http.v2.Test +Container.com.yahoo.vespa.config.server.http.v2.request.Test +Container.com.yahoo.vespa.config.server.http.v2.response.Test +Container.com.yahoo.vespa.config.server.maintenance.Test +Container.com.yahoo.vespa.config.server.metrics.Test +Container.com.yahoo.vespa.config.server.model.Test +Container.com.yahoo.vespa.config.server.modelfactory.Test +Container.com.yahoo.vespa.config.server.monitoring.Test +Container.com.yahoo.vespa.config.server.provision.Test +Container.com.yahoo.vespa.config.server.rpc.Test +Container.com.yahoo.vespa.config.server.rpc.security.Test +Container.com.yahoo.vespa.config.server.session.Test +Container.com.yahoo.vespa.config.server.tenant.Test +Container.com.yahoo.vespa.config.server.version.Test +Container.com.yahoo.vespa.config.server.zookeeper.Test +Container.com.yahoo.vespa.config.storage.Test +Container.com.yahoo.vespa.config.util.Test +Container.com.yahoo.vespa.curator.Test +Container.com.yahoo.vespa.curator.api.Test +Container.com.yahoo.vespa.curator.mock.Test +Container.com.yahoo.vespa.curator.recipes.Test +Container.com.yahoo.vespa.curator.stats.Test +Container.com.yahoo.vespa.curator.transaction.Test +Container.com.yahoo.vespa.defaults.Test +Container.com.yahoo.vespa.document.Test +Container.com.yahoo.vespa.document.dom.Test +Container.com.yahoo.vespa.documentmodel.Test +Container.com.yahoo.vespafeeder.Test +Container.com.yahoo.vespa.feed.perf.Test +Container.com.yahoo.vespa.filedistribution.Test +Container.com.yahoo.vespa.filedistribution.status.Test +Container.com.yahoo.vespa.flags.Test +Container.com.yahoo.vespa.flags.custom.Test +Container.com.yahoo.vespa.flags.file.Test +Container.com.yahoo.vespa.flags.json.Test +Container.com.yahoo.vespa.flags.json.wire.Test +Container.com.yahoo.vespaget.Test +Container.com.yahoo.vespa.hadoop.Test +Container.com.yahoo.vespa.hadoop.mapreduce.Test +Container.com.yahoo.vespa.hadoop.mapreduce.util.Test +Container.com.yahoo.vespa.hadoop.pig.Test +Container.com.yahoo.vespa.hosted.athenz.instanceproviderservice.Test +Container.com.yahoo.vespa.hosted.athenz.instanceproviderservice.config.Test +Container.com.yahoo.vespa.hosted.ca.Test +Container.com.yahoo.vespa.hosted.ca.instance.Test +Container.com.yahoo.vespa.hosted.ca.restapi.Test +Container.com.yahoo.vespa.hosted.controller.Test +Container.com.yahoo.vespa.hosted.controller.api.application.v4.Test +Container.com.yahoo.vespa.hosted.controller.api.application.v4.model.Test +Container.com.yahoo.vespa.hosted.controller.api.application.v4.model.configserverbindings.Test +Container.com.yahoo.vespa.hosted.controller.api.configserver.Test +Container.com.yahoo.vespa.hosted.controller.api.identifiers.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.archive.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.artifact.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.athenz.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.aws.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.billing.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.certificates.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.configserver.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.deployment.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.dns.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.entity.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.horizon.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.jira.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.maven.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.noderepository.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.organization.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.repair.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.resource.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.routing.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.secrets.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.stubs.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.user.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.vcmr.Test +Container.com.yahoo.vespa.hosted.controller.api.integration.zone.Test +Container.com.yahoo.vespa.hosted.controller.api.role.Test +Container.com.yahoo.vespa.hosted.controller.api.systemflags.v1.Test +Container.com.yahoo.vespa.hosted.controller.api.systemflags.v1.wire.Test +Container.com.yahoo.vespa.hosted.controller.application.Test +Container.com.yahoo.vespa.hosted.controller.application.pkg.Test +Container.com.yahoo.vespa.hosted.controller.archive.Test +Container.com.yahoo.vespa.hosted.controller.athenz.Test +Container.com.yahoo.vespa.hosted.controller.athenz.config.Test +Container.com.yahoo.vespa.hosted.controller.athenz.impl.Test +Container.com.yahoo.vespa.hosted.controller.auditlog.Test +Container.com.yahoo.vespa.hosted.controller.certificate.Test +Container.com.yahoo.vespa.hosted.controller.concurrent.Test +Container.com.yahoo.vespa.hosted.controller.deployment.Test +Container.com.yahoo.vespa.hosted.controller.dns.Test +Container.com.yahoo.vespa.hosted.controller.maintenance.Test +Container.com.yahoo.vespa.hosted.controller.metric.Test +Container.com.yahoo.vespa.hosted.controller.notification.Test +Container.com.yahoo.vespa.hosted.controller.persistence.Test +Container.com.yahoo.vespa.hosted.controller.proxy.Test +Container.com.yahoo.vespa.hosted.controller.restapi.application.Test +Container.com.yahoo.vespa.hosted.controller.restapi.athenz.Test +Container.com.yahoo.vespa.hosted.controller.restapi.billing.Test +Container.com.yahoo.vespa.hosted.controller.restapi.changemanagement.Test +Container.com.yahoo.vespa.hosted.controller.restapi.configserver.Test +Container.com.yahoo.vespa.hosted.controller.restapi.controller.Test +Container.com.yahoo.vespa.hosted.controller.restapi.deployment.Test +Container.com.yahoo.vespa.hosted.controller.restapi.filter.Test +Container.com.yahoo.vespa.hosted.controller.restapi.flags.Test +Container.com.yahoo.vespa.hosted.controller.restapi.horizon.Test +Container.com.yahoo.vespa.hosted.controller.restapi.os.Test +Container.com.yahoo.vespa.hosted.controller.restapi.routing.Test +Container.com.yahoo.vespa.hosted.controller.restapi.systemflags.Test +Container.com.yahoo.vespa.hosted.controller.restapi.user.Test +Container.com.yahoo.vespa.hosted.controller.restapi.zone.v1.Test +Container.com.yahoo.vespa.hosted.controller.restapi.zone.v2.Test +Container.com.yahoo.vespa.hosted.controller.routing.Test +Container.com.yahoo.vespa.hosted.controller.routing.context.Test +Container.com.yahoo.vespa.hosted.controller.routing.rotation.Test +Container.com.yahoo.vespa.hosted.controller.security.Test +Container.com.yahoo.vespa.hosted.controller.support.access.Test +Container.com.yahoo.vespa.hosted.controller.tenant.Test +Container.com.yahoo.vespa.hosted.controller.tls.Test +Container.com.yahoo.vespa.hosted.controller.versions.Test +Container.com.yahoo.vespa.hosted.node.admin.Test +Container.com.yahoo.vespa.hosted.node.admin.component.Test +Container.com.yahoo.vespa.hosted.node.admin.configserver.Test +Container.com.yahoo.vespa.hosted.node.admin.configserver.flags.Test +Container.com.yahoo.vespa.hosted.node.admin.configserver.noderepository.Test +Container.com.yahoo.vespa.hosted.node.admin.configserver.noderepository.bindings.Test +Container.com.yahoo.vespa.hosted.node.admin.configserver.noderepository.reports.Test +Container.com.yahoo.vespa.hosted.node.admin.configserver.orchestrator.Test +Container.com.yahoo.vespa.hosted.node.admin.configserver.state.Test +Container.com.yahoo.vespa.hosted.node.admin.configserver.state.bindings.Test +Container.com.yahoo.vespa.hosted.node.admin.container.Test +Container.com.yahoo.vespa.hosted.node.admin.container.image.Test +Container.com.yahoo.vespa.hosted.node.admin.container.metrics.Test +Container.com.yahoo.vespa.hosted.node.admin.maintenance.Test +Container.com.yahoo.vespa.hosted.node.admin.maintenance.acl.Test +Container.com.yahoo.vespa.hosted.node.admin.maintenance.coredump.Test +Container.com.yahoo.vespa.hosted.node.admin.maintenance.disk.Test +Container.com.yahoo.vespa.hosted.node.admin.maintenance.identity.Test +Container.com.yahoo.vespa.hosted.node.admin.maintenance.servicedump.Test +Container.com.yahoo.vespa.hosted.node.admin.maintenance.sync.Test +Container.com.yahoo.vespa.hosted.node.admin.nodeadmin.Test +Container.com.yahoo.vespa.hosted.node.admin.nodeagent.Test +Container.com.yahoo.vespa.hosted.node.admin.provider.Test +Container.com.yahoo.vespa.hosted.node.admin.task.util.Test +Container.com.yahoo.vespa.hosted.node.admin.task.util.editor.Test +Container.com.yahoo.vespa.hosted.node.admin.task.util.file.Test +Container.com.yahoo.vespa.hosted.node.admin.task.util.fs.Test +Container.com.yahoo.vespa.hosted.node.admin.task.util.network.Test +Container.com.yahoo.vespa.hosted.node.admin.task.util.process.Test +Container.com.yahoo.vespa.hosted.node.admin.task.util.systemd.Test +Container.com.yahoo.vespa.hosted.node.admin.task.util.template.Test +Container.com.yahoo.vespa.hosted.node.admin.task.util.text.Test +Container.com.yahoo.vespa.hosted.node.admin.task.util.yum.Test +Container.com.yahoo.vespa.hosted.provision.Test +Container.com.yahoo.vespa.hosted.provision.applications.Test +Container.com.yahoo.vespa.hosted.provision.autoscale.Test +Container.com.yahoo.vespa.hosted.provision.lb.Test +Container.com.yahoo.vespa.hosted.provision.maintenance.Test +Container.com.yahoo.vespa.hosted.provision.node.Test +Container.com.yahoo.vespa.hosted.provision.node.filter.Test +Container.com.yahoo.vespa.hosted.provision.os.Test +Container.com.yahoo.vespa.hosted.provision.persistence.Test +Container.com.yahoo.vespa.hosted.provision.provisioning.Test +Container.com.yahoo.vespa.hosted.provision.restapi.Test +Container.com.yahoo.vespa.hosted.provision.testutils.Test +Container.com.yahoo.vespa.hosted.routing.Test +Container.com.yahoo.vespa.hosted.routing.nginx.Test +Container.com.yahoo.vespa.hosted.routing.restapi.Test +Container.com.yahoo.vespa.hosted.routing.status.Test +Container.com.yahoo.vespa.hosted.testrunner.Test +Container.com.yahoo.vespa.http.server.Test +Container.com.yahoo.vespa.http.server.util.Test +Container.com.yahoo.vespa.indexinglanguage.Test +Container.com.yahoo.vespa.indexinglanguage.expressions.Test +Container.com.yahoo.vespa.indexinglanguage.linguistics.Test +Container.com.yahoo.vespa.indexinglanguage.parser.Test +Container.com.yahoo.vespa.indexinglanguage.predicate.Test +Container.com.yahoo.vespa.jaxrs.annotation.Test +Container.com.yahoo.vespa.maven.plugin.enforcer.Test +Container.com.yahoo.vespa.model.Test +Container.com.yahoo.vespa.model.admin.Test +Container.com.yahoo.vespa.model.admin.clustercontroller.Test +Container.com.yahoo.vespa.model.admin.metricsproxy.Test +Container.com.yahoo.vespa.model.admin.monitoring.Test +Container.com.yahoo.vespa.model.admin.monitoring.builder.Test +Container.com.yahoo.vespa.model.admin.monitoring.builder.xml.Test +Container.com.yahoo.vespa.model.application.validation.Test +Container.com.yahoo.vespa.model.application.validation.change.Test +Container.com.yahoo.vespa.model.application.validation.change.search.Test +Container.com.yahoo.vespa.model.application.validation.first.Test +Container.com.yahoo.vespa.model.builder.Test +Container.com.yahoo.vespa.model.builder.xml.dom.Test +Container.com.yahoo.vespa.model.builder.xml.dom.chains.Test +Container.com.yahoo.vespa.model.builder.xml.dom.chains.docproc.Test +Container.com.yahoo.vespa.model.builder.xml.dom.chains.processing.Test +Container.com.yahoo.vespa.model.builder.xml.dom.chains.search.Test +Container.com.yahoo.vespa.model.clients.Test +Container.com.yahoo.vespa.model.container.Test +Container.com.yahoo.vespa.model.container.component.Test +Container.com.yahoo.vespa.model.container.component.chain.Test +Container.com.yahoo.vespa.model.container.configserver.Test +Container.com.yahoo.vespa.model.container.configserver.option.Test +Container.com.yahoo.vespa.model.container.docproc.Test +Container.com.yahoo.vespa.model.container.docproc.model.Test +Container.com.yahoo.vespa.model.container.http.Test +Container.com.yahoo.vespa.model.container.http.ssl.Test +Container.com.yahoo.vespa.model.container.http.xml.Test +Container.com.yahoo.vespa.model.container.ml.Test +Container.com.yahoo.vespa.model.container.processing.Test +Container.com.yahoo.vespa.model.container.search.Test +Container.com.yahoo.vespa.model.container.search.searchchain.Test +Container.com.yahoo.vespa.model.container.search.searchchain.defaultsearchchains.Test +Container.com.yahoo.vespa.model.container.xml.Test +Container.com.yahoo.vespa.model.container.xml.document.Test +Container.com.yahoo.vespa.model.container.xml.embedder.Test +Container.com.yahoo.vespa.model.content.Test +Container.com.yahoo.vespa.model.content.cluster.Test +Container.com.yahoo.vespa.model.content.engines.Test +Container.com.yahoo.vespa.model.content.storagecluster.Test +Container.com.yahoo.vespa.model.filedistribution.Test +Container.com.yahoo.vespa.model.ml.Test +Container.com.yahoo.vespa.model.routing.Test +Container.com.yahoo.vespa.model.search.Test +Container.com.yahoo.vespa.model.utils.Test +Container.com.yahoo.vespa.model.utils.internal.Test +Container.com.yahoo.vespa.objects.Test +Container.com.yahoo.vespa.orchestrator.Test +Container.com.yahoo.vespa.orchestrator.config.Test +Container.com.yahoo.vespa.orchestrator.controller.Test +Container.com.yahoo.vespa.orchestrator.model.Test +Container.com.yahoo.vespa.orchestrator.policy.Test +Container.com.yahoo.vespa.orchestrator.resources.Test +Container.com.yahoo.vespa.orchestrator.restapi.wire.Test +Container.com.yahoo.vespa.orchestrator.status.Test +Container.com.yahoo.vespa.orchestrator.status.json.Test +Container.com.yahoo.vespa.security.tool.securityenv.Test +Container.com.yahoo.vespa.service.duper.Test +Container.com.yahoo.vespa.service.executor.Test +Container.com.yahoo.vespa.service.health.Test +Container.com.yahoo.vespa.service.manager.Test +Container.com.yahoo.vespa.service.model.Test +Container.com.yahoo.vespa.service.monitor.Test +Container.com.yahoo.vespa.service.slobrok.Test +Container.com.yahoo.vespastat.Test +Container.com.yahoo.vespa.streamingvisitors.Test +Container.com.yahoo.vespa.streamingvisitors.tracing.Test +Container.com.yahoo.vespasummarybenchmark.Test +Container.com.yahoo.vespa.test.file.Test +Container.com.yahoo.vespa.testrunner.Test +Container.com.yahoo.vespavisit.Test +Container.com.yahoo.vespaxmlparser.Test +Container.com.yahoo.vespa.zookeeper.Test +Container.com.yahoo.vespa.zookeeper.cli.Test +Container.com.yahoo.vespa.zookeeper.client.Test +Container.com.yahoo.yolean.Test +Container.com.yahoo.yolean.chain.Test +Container.com.yahoo.yolean.concurrent.Test +Container.com.yahoo.yolean.function.Test +Container.com.yahoo.yolean.system.Test +Container.com.yahoo.yolean.trace.Test diff --git a/client/go/cmd/logfmt/internal_notnames.txt b/client/go/cmd/logfmt/internal_notnames.txt new file mode 100644 index 00000000000..49543758ac3 --- /dev/null +++ b/client/go/cmd/logfmt/internal_notnames.txt @@ -0,0 +1,8 @@ +Container.ai.onnx.Test +Container.com.fasterxml.jackson.jaxrs.json.Test +Container.com.google.Test +Container.com.yahooapis.foo.Test +Container.com.yahoo.newssearch.Test +Container.com.yahoo.Test +Container.com.yahoo.testing.Test +Container.org.apache.http.Test diff --git a/client/go/cmd/logfmt/internal_test.go b/client/go/cmd/logfmt/internal_test.go new file mode 100644 index 00000000000..9b6b0f8404c --- /dev/null +++ b/client/go/cmd/logfmt/internal_test.go @@ -0,0 +1,34 @@ +package logfmt + +import ( + "bufio" + "os" + "testing" +) + +// tests: func isInternal(componentName string) bool + +func TestIsInternal(t *testing.T) { + f, err := os.Open("internal_names.txt") + if err != nil { + t.Fatal("could not read test data") + } + defer f.Close() + for input := bufio.NewScanner(f); input.Scan(); { + if name := input.Text(); !isInternal(name) { + t.Logf("name '%s' should be internal but was not recognized", name) + t.Fail() + } + } + f, err = os.Open("internal_notnames.txt") + if err != nil { + t.Fatal("could not read test data") + } + defer f.Close() + for input := bufio.NewScanner(f); input.Scan(); { + if name := input.Text(); isInternal(name) { + t.Logf("name '%s' should not be internal but was recognized", name) + t.Fail() + } + } +} diff --git a/client/go/cmd/logfmt/levelflags.go b/client/go/cmd/logfmt/levelflags.go new file mode 100644 index 00000000000..4e6c1284753 --- /dev/null +++ b/client/go/cmd/logfmt/levelflags.go @@ -0,0 +1,72 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "strings" +) + +// handle CLI flags for log level filtering + +type flagValueForLevel struct { + levels map[string]bool + changed bool +} + +func defaultLevelFlags() map[string]bool { + return map[string]bool{ + "fatal": true, + "error": true, + "warning": true, + "info": true, + "config": false, + "event": false, + "debug": false, + "spam": false, + } +} + +func (v *flagValueForLevel) Type() string { + return "level flags" +} + +func (v *flagValueForLevel) String() string { + var buf strings.Builder + flagNames := []string{ + "fatal", + "error", + "warning", + "info", + "config", + "event", + "debug", + "spam", + } + for _, flag := range flagNames { + if v.levels[flag] { + buf.WriteString(" +") + } else { + buf.WriteString(" -") + } + buf.WriteString(flag) + } + return buf.String() +} + +func (v *flagValueForLevel) flags() map[string]bool { + return v.levels +} + +func (v *flagValueForLevel) name() string { + return "level" +} + +func (v *flagValueForLevel) unchanged() bool { + return !v.changed +} + +func (v *flagValueForLevel) Set(val string) error { + return applyPlusMinus(val, v) +} diff --git a/client/go/cmd/logfmt/levelflags_test.go b/client/go/cmd/logfmt/levelflags_test.go new file mode 100644 index 00000000000..186ea2d96b0 --- /dev/null +++ b/client/go/cmd/logfmt/levelflags_test.go @@ -0,0 +1,74 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "strings" + "testing" +) + +func TestLevelFlags(t *testing.T) { + none := " -fatal -error -warning -info -config -event -debug -spam" + + var flag flagValueForLevel + if flag.String() != none { + t.Logf("unset flag displays as '%s', expected '%s'", flag.String(), none) + t.Fail() + } + if flag.Type() != "level flags" { + t.Logf("flag type was '%s'", flag.Type()) + t.Fail() + } + check := func(expected string, texts ...string) { + var target flagValueForLevel + // target.levels = defaultLevelFlags() + target.levels = defaultLevelFlags() + for _, text := range texts { + err := target.Set(text) + if err != nil { + t.Fatalf("unexpected error with level flags Set('%s'): %v", text, err) + } + } + got := target.String() + if got != expected { + t.Logf("expected flags [%s] but got: [%s]", expected, got) + t.Fail() + } + } + check(" +fatal +error +warning +info -config -event -debug -spam") + check(" -fatal -error -warning -info -config -event -debug -spam", "-all") + check(" +fatal +error +warning +info +config +event +debug +spam", "all") + check(" +fatal +error +warning +info +config +event +debug +spam", "+all") + check(" -fatal -error -warning -info -config -event +debug -spam", "debug") + check(" +fatal +error +warning +info +config +event +debug -spam", "all-spam") + check(" +fatal +error +warning +info +config +event +debug -spam", "all", "-spam") + check(" +fatal +error +warning -info -config +event -debug -spam", "+event", "-info") + check(" +fatal +error -warning -info -config +event -debug -spam", "+event,-info,-warning,config") + check(" +fatal +error -warning -info +config +event -debug -spam", "+event,-info,-warning,+config") + check(" +fatal +error -warning -info +config +event -debug -spam", "+event,-info", "-warning,+config") + check(" -fatal -error -warning -info +config -event -debug -spam", "+event", "-info", "-warning", "config") + check = func(expectErr string, texts ...string) { + var target flagValueForLevel + target.levels = defaultLevelFlags() + for _, text := range texts { + err := target.Set(text) + if err != nil { + if err.Error() == expectErr { + return + } + t.Fatalf("expected error [%s] with level flags Set('%s'), but got [%v]", expectErr, text, err) + } + } + t.Logf("Did not get expected error '%s' from %s", expectErr, strings.Join(texts, ",")) + t.Fail() + } + check("not a valid level flag: 'foo'", "foo") + check("not a valid level flag: 'foo'", "event,foo,config") + check("not a valid level flag: 'foo'", "-event,-foo,-config") + check("not a valid level flag: 'foo'", "+event,+foo,+config") + check("not a valid level flag: 'foo'", "event", "foo", "config") + check("not a valid level flag: 'foo'", "-event", "-foo", "-config") + check("not a valid level flag: 'foo'", "+event", "+foo", "+config") +} diff --git a/client/go/cmd/logfmt/options.go b/client/go/cmd/logfmt/options.go new file mode 100644 index 00000000000..f564ffd4df0 --- /dev/null +++ b/client/go/cmd/logfmt/options.go @@ -0,0 +1,47 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "fmt" + "os" +) + +// options designed for compatibility with perl version of vespa-logfmt + +type Options struct { + ShowFields flagValueForShow + ShowLevels flagValueForLevel + OnlyHostname string + OnlyPid string + OnlyService string + OnlyInternal bool + FollowTail bool + DequoteNewlines bool + TruncateService bool + TruncateComponent bool + ComponentFilter regexFlag + MessageFilter regexFlag +} + +func NewOptions() (ret Options) { + ret.ShowLevels.levels = defaultLevelFlags() + ret.ShowFields.shown = defaultShowFlags() + return +} + +func (o *Options) showField(field string) bool { + return o.ShowFields.shown[field] +} + +func (o *Options) showLevel(level string) bool { + rv, ok := o.ShowLevels.levels[level] + if !ok { + o.ShowLevels.levels[level] = true + fmt.Fprintf(os.Stderr, "Warnings: unknown level '%s' in input\n", level) + return true + } + return rv +} diff --git a/client/go/cmd/logfmt/plusminusflag.go b/client/go/cmd/logfmt/plusminusflag.go new file mode 100644 index 00000000000..1768cf0e7be --- /dev/null +++ b/client/go/cmd/logfmt/plusminusflag.go @@ -0,0 +1,67 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "fmt" + "strings" +) + +// common code for showFlags and levelFlags + +type plusMinusFlag interface { + flags() map[string]bool + name() string + unchanged() bool +} + +func trimPrefix(value, prefix string) (newValue string, hadPrefix bool) { + hadPrefix = strings.HasPrefix(value, prefix) + if hadPrefix { + newValue = strings.TrimPrefix(value, prefix) + } else { + newValue = value + } + return +} + +func applyPlusMinus(val string, target plusMinusFlag) error { + minus := strings.HasPrefix(val, "-") + plus := strings.HasPrefix(val, "+") + val = strings.ReplaceAll(val, "-", ",-") + val = strings.ReplaceAll(val, "+", ",+") + if target.unchanged() { + // user wants to reset flags? + if minus == false && plus == false { + for k, _ := range target.flags() { + target.flags()[k] = false + } + } + } + changeTo := !minus + for _, k := range strings.Split(val, ",") { + if suppress, minus := trimPrefix(k, "-"); minus { + k = suppress + changeTo = false + } + if surface, plus := trimPrefix(k, "+"); plus { + k = surface + changeTo = true + } + if k == "" { + continue + } + if k == "all" { + for k, _ := range target.flags() { + target.flags()[k] = changeTo + } + } else if _, ok := target.flags()[k]; !ok { + return fmt.Errorf("not a valid %s flag: '%s'", target.name(), k) + } else { + target.flags()[k] = changeTo + } + } + return nil +} diff --git a/client/go/cmd/logfmt/regexflag.go b/client/go/cmd/logfmt/regexflag.go new file mode 100644 index 00000000000..8f7d2a91373 --- /dev/null +++ b/client/go/cmd/logfmt/regexflag.go @@ -0,0 +1,38 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "regexp" +) + +// optional regular expression filter, as a CLI flag + +type regexFlag struct { + regex *regexp.Regexp +} + +func (re regexFlag) unmatched(s string) bool { + if re.regex == nil { + return false + } + return re.regex.FindStringIndex(s) == nil +} + +func (v *regexFlag) Type() string { + return "regular expression" +} + +func (v *regexFlag) String() string { + if v.regex == nil { + return "<none>" + } + return v.regex.String() +} + +func (v *regexFlag) Set(val string) (r error) { + v.regex, r = regexp.Compile(val) + return +} diff --git a/client/go/cmd/logfmt/regexflag_test.go b/client/go/cmd/logfmt/regexflag_test.go new file mode 100644 index 00000000000..489439863a2 --- /dev/null +++ b/client/go/cmd/logfmt/regexflag_test.go @@ -0,0 +1,41 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "testing" +) + +func assertMatch(t *testing.T, re string, flag *regexFlag, texts ...string) { + t.Helper() + err := flag.Set(re) + require.Nil(t, err, "unexpected error with flag.Set('%s'): %v", re, err) + assert.Equal(t, re, flag.String(), "set flag displays as '%s', expected '%s'", flag.String(), re) + for _, text := range texts { + assert.False(t, flag.unmatched(text), "flag '%s' claims a non-match for '%s'", flag.String(), text) + } +} + +func assertUnmatch(t *testing.T, re string, flag *regexFlag, texts ...string) { + t.Helper() + err := flag.Set(re) + require.Nil(t, err, "unexpected error with flag.Set('%s'): %v", re, err) + assert.Equal(t, re, flag.String()) + for _, text := range texts { + assert.True(t, flag.unmatched(text), "flag '%s' should claim a non-match for '%s'", flag.String(), text) + } +} + +func TestRegexFlag(t *testing.T) { + var flag regexFlag + assert.Equal(t, "<none>", flag.String()) + assert.Equal(t, "regular expression", flag.Type()) + assert.False(t, flag.unmatched("foobar"), "unset flag claims a non-match") + assert.EqualError(t, flag.Set("*"), "error parsing regexp: missing argument to repetition operator: `*`") + assertMatch(t, "foo.*bar", new(regexFlag), "foobar", "foo bar", "x foobar y", "xfoobary", "xfooybarz") + assertUnmatch(t, "foo.*bar", new(regexFlag), "Foobar", "foo Bar", "fxoobar", "whatever") +} diff --git a/client/go/cmd/logfmt/runlogfmt.go b/client/go/cmd/logfmt/runlogfmt.go new file mode 100644 index 00000000000..9d782692f50 --- /dev/null +++ b/client/go/cmd/logfmt/runlogfmt.go @@ -0,0 +1,78 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "bufio" + "fmt" + "os" + + "github.com/mattn/go-isatty" +) + +func inputIsTty() bool { + return isatty.IsTerminal(os.Stdin.Fd()) +} + +func vespaHome() string { + ev := os.Getenv("VESPA_HOME") + if ev == "" { + return "/opt/vespa" + } + return ev +} + +// main entry point for vespa-logfmt + +func RunLogfmt(opts *Options, args []string) { + if len(args) == 0 { + if inputIsTty() { + args = append(args, vespaHome()+"/logs/vespa/vespa.log") + } else { + formatFile(opts, os.Stdin) + } + } + if opts.FollowTail { + if len(args) != 1 { + fmt.Fprintf(os.Stderr, "Must have exact 1 file for 'follow' option, got %d\n", len(args)) + return + } + tailFile(opts, args[0]) + return + } + for _, arg := range args { + file, err := os.Open(arg) + if err != nil { + fmt.Fprintf(os.Stderr, "Cannot open '%s': %v\n", arg, err) + } else { + formatFile(opts, file) + file.Close() + } + } +} + +func formatLine(opts *Options, line string) { + output, err := handleLine(opts, line) + if err != nil { + fmt.Fprintln(os.Stderr, "bad log line:", err) + } else { + os.Stdout.WriteString(output) + } +} + +func tailFile(opts *Options, fn string) { + tailed := FollowFile(fn) + for line := range tailed.Lines { + formatLine(opts, line.Text) + } +} + +func formatFile(opts *Options, arg *os.File) { + input := bufio.NewScanner(arg) + input.Buffer(make([]byte, 64*1024), 4*1024*1024) + for input.Scan() { + formatLine(opts, input.Text()) + } +} diff --git a/client/go/cmd/logfmt/showflags.go b/client/go/cmd/logfmt/showflags.go new file mode 100644 index 00000000000..b69860e0312 --- /dev/null +++ b/client/go/cmd/logfmt/showflags.go @@ -0,0 +1,76 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "strings" +) + +// handle CLI flags for which fields to show when formatting a line + +type flagValueForShow struct { + shown map[string]bool + changed bool +} + +func defaultShowFlags() map[string]bool { + return map[string]bool{ + "time": true, + "fmttime": true, + "msecs": true, + "usecs": false, + "host": false, + "level": true, + "pid": false, + "service": true, + "component": true, + "message": true, + } +} + +func (v *flagValueForShow) Type() string { + return "show flags" +} + +func (v *flagValueForShow) String() string { + var buf strings.Builder + flagNames := []string{ + "time", + "fmttime", + "msecs", + "usecs", + "host", + "level", + "pid", + "service", + "component", + "message", + } + for _, flag := range flagNames { + if v.shown[flag] { + buf.WriteString(" +") + } else { + buf.WriteString(" -") + } + buf.WriteString(flag) + } + return buf.String() +} + +func (v *flagValueForShow) flags() map[string]bool { + return v.shown +} + +func (v *flagValueForShow) name() string { + return "show" +} + +func (v *flagValueForShow) unchanged() bool { + return !v.changed +} + +func (v *flagValueForShow) Set(val string) error { + return applyPlusMinus(val, v) +} diff --git a/client/go/cmd/logfmt/showflags_test.go b/client/go/cmd/logfmt/showflags_test.go new file mode 100644 index 00000000000..d1b66118afd --- /dev/null +++ b/client/go/cmd/logfmt/showflags_test.go @@ -0,0 +1,61 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "strings" + "testing" +) + +func TestShowFlags(t *testing.T) { + none := " -time -fmttime -msecs -usecs -host -level -pid -service -component -message" + var flag flagValueForShow + assert.Equal(t, none, flag.String(), "unset flag displays as '%s', expected '%s'", flag.String(), none) + assert.Equal(t, "show flags", flag.Type()) + check := func(expected string, texts ...string) { + var target flagValueForShow + // target.levels = defaultLevelFlags() + target.shown = defaultShowFlags() + for _, text := range texts { + err := target.Set(text) + require.Nil(t, err, "unexpected error with show flags Set('%s'): %v", text, err) + } + assert.Equal(t, expected, target.String()) + } + check(" +time +fmttime +msecs -usecs -host +level -pid +service +component +message") + check(" -time -fmttime -msecs -usecs -host -level -pid -service -component -message", "-all") + check(" +time +fmttime +msecs +usecs +host +level +pid +service +component +message", "all") + check(" +time +fmttime +msecs +usecs +host +level +pid +service +component +message", "+all") + check(" -time -fmttime -msecs -usecs -host -level +pid -service -component -message", "pid") + check(" +time +fmttime +msecs +usecs -host +level +pid +service +component +message", "all-host") + check(" +time +fmttime +msecs +usecs -host +level +pid +service +component +message", "all", "-host") + check(" +time +fmttime -msecs -usecs -host +level +pid +service +component +message", "+pid", "-msecs") + check(" +time -fmttime +msecs -usecs +host +level -pid -service +component +message", "+host,-fmttime,-service,pid") + check(" +time -fmttime +msecs -usecs +host +level +pid -service +component +message", "+host,-fmttime,-service,+pid") + check(" +time -fmttime +msecs -usecs +host +level +pid -service +component +message", "+host,-fmttime", "-service,+pid") + check(" -time -fmttime -msecs -usecs -host -level +pid -service -component -message", "+host", "-fmttime", "-service", "pid") + check = func(expectErr string, texts ...string) { + var target flagValueForShow + target.shown = defaultShowFlags() + for _, text := range texts { + err := target.Set(text) + if err != nil { + require.Equal(t, expectErr, err.Error()) + return + } + } + t.Logf("Did not get expected error [%s] from %s", expectErr, strings.Join(texts, " ")) + t.Fail() + } + check("not a valid show flag: 'foo'", "foo") + check("not a valid show flag: 'foo'", "level,foo,message") + check("not a valid show flag: 'foo'", "-level,-foo,-message") + check("not a valid show flag: 'foo'", "+level,+foo,+message") + check("not a valid show flag: 'foo'", "level", "foo", "message") + check("not a valid show flag: 'foo'", "-level", "-foo", "-message") + check("not a valid show flag: 'foo'", "+level", "+foo", "+message") +} diff --git a/client/go/cmd/logfmt/tail.go b/client/go/cmd/logfmt/tail.go new file mode 100644 index 00000000000..443656436c1 --- /dev/null +++ b/client/go/cmd/logfmt/tail.go @@ -0,0 +1,156 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// vespa logfmt command +// Author: arnej + +package logfmt + +import ( + "bufio" + "fmt" + "io" + "os" + "time" +) + +const lastLinesSize = 4 * 1024 + +type Line struct { + Text string +} + +// an active "tail -f" like object + +type Tail struct { + Lines chan Line + lineBuf []byte + curFile *os.File + fn string + reader *bufio.Reader +} + +// API for starting to follow a log file + +func FollowFile(fn string) (res Tail) { + res.fn = fn + res.lineBuf = make([]byte, lastLinesSize) + res.openTail() + res.Lines = make(chan Line, 20) + res.lineBuf = res.lineBuf[:0] + go runTailWith(&res) + return res +} + +func (t *Tail) setFile(f *os.File) { + if t.curFile != nil { + t.curFile.Close() + } + t.curFile = f + if f != nil { + t.reader = bufio.NewReaderSize(f, 1024*1024) + } else { + t.reader = nil + } +} + +// open log file and seek to the start of a line near the end, if possible. +func (t *Tail) openTail() { + file, err := os.Open(t.fn) + if err != nil { + return + } + sz, err := file.Seek(0, os.SEEK_END) + if err != nil { + return + } + if sz < lastLinesSize { + sz, err = file.Seek(0, os.SEEK_SET) + if err == nil { + // just read from start of file, all OK + t.setFile(file) + } + return + } + sz, _ = file.Seek(-lastLinesSize, os.SEEK_END) + n, err := file.Read(t.lineBuf) + if err != nil { + return + } + for i := 0; i < n; i++ { + if t.lineBuf[i] == '\n' { + sz, err = file.Seek(sz+int64(i+1), os.SEEK_SET) + if err == nil { + t.setFile(file) + } + return + } + } +} + +func (t *Tail) reopen(oldSize int64) { + for cnt := 0; cnt < 100; cnt++ { + file, r := os.Open(t.fn) + if r != nil { + t.setFile(nil) + if cnt == 0 { + fmt.Fprintf(os.Stderr, "%v (waiting for log file to appear)\n", r) + } + time.Sleep(1000 * time.Millisecond) + continue + } + sz, _ := file.Seek(0, os.SEEK_END) + if sz != oldSize { + file.Seek(0, os.SEEK_SET) + if t.curFile != nil { + t.curFile.Close() + } + t.setFile(file) + } else { + // same size, same file (probably), continue following it + file.Close() + } + return + } +} + +// runs as a goroutine +func runTailWith(t *Tail) { + defer t.setFile(nil) +loop: + for { + for t.curFile == nil { + t.reopen(-1) + } + bytes, err := t.reader.ReadSlice('\n') + t.lineBuf = append(t.lineBuf, bytes...) + if err == bufio.ErrBufferFull { + continue + } + if err == nil { + ll := len(t.lineBuf) - 1 + t.Lines <- Line{Text: string(t.lineBuf[:ll])} + t.lineBuf = t.lineBuf[:0] + continue + } + if err == io.EOF { + pos, _ := t.curFile.Seek(0, os.SEEK_CUR) + for cnt := 0; cnt < 100; cnt++ { + time.Sleep(10 * time.Millisecond) + sz, _ := t.curFile.Seek(0, os.SEEK_END) + if sz != pos { + if sz < pos { + // truncation case + pos = 0 + } + t.curFile.Seek(pos, os.SEEK_SET) + continue loop + } + } + // no change in file size, try reopening + t.reopen(pos) + } else { + fmt.Fprintf(os.Stderr, "error tailing '%s': %v\n", t.fn, err) + close(t.Lines) + return + } + } +} |