aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArne Juul <arnej@yahooinc.com>2022-07-25 13:21:50 +0000
committerArne Juul <arnej@yahooinc.com>2022-08-09 08:23:15 +0000
commit8e5c5def940890425d8a93e8afcad0980a0571d9 (patch)
treeda297891365817c35c51eb1d4411c5cc9a24ffcb
parent9dd6112864140a346ad1c1de0522656365deb7c0 (diff)
add logfmt code
* our own "tail -f" implementation in tail.go * filtering and formatting on per-line basis in handleline.go * recognition of vespa-internal components in internal.go * cobra-compatible flags for "level" in levelflags.go * cobra-compatible flags for "show" in showflags.go * cobra-compatible flag for regex handling in regexflag.go * options designed for compatibility with perl version in options.go * entrypoint in runlogfmt.go
-rw-r--r--client/go/cmd/logfmt/handleline.go116
-rw-r--r--client/go/cmd/logfmt/internal.go106
-rw-r--r--client/go/cmd/logfmt/internal_names.txt782
-rw-r--r--client/go/cmd/logfmt/internal_notnames.txt8
-rw-r--r--client/go/cmd/logfmt/internal_test.go34
-rw-r--r--client/go/cmd/logfmt/levelflags.go72
-rw-r--r--client/go/cmd/logfmt/levelflags_test.go74
-rw-r--r--client/go/cmd/logfmt/options.go47
-rw-r--r--client/go/cmd/logfmt/plusminusflag.go67
-rw-r--r--client/go/cmd/logfmt/regexflag.go38
-rw-r--r--client/go/cmd/logfmt/regexflag_test.go41
-rw-r--r--client/go/cmd/logfmt/runlogfmt.go78
-rw-r--r--client/go/cmd/logfmt/showflags.go76
-rw-r--r--client/go/cmd/logfmt/showflags_test.go61
-rw-r--r--client/go/cmd/logfmt/tail.go156
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
+ }
+ }
+}