From commits-return-5989-archive-asf-public=cust-asf.ponee.io@openwhisk.apache.org Thu Oct 4 09:55:50 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id E4166180658 for ; Thu, 4 Oct 2018 09:55:49 +0200 (CEST) Received: (qmail 16254 invoked by uid 500); 4 Oct 2018 07:55:49 -0000 Mailing-List: contact commits-help@openwhisk.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openwhisk.apache.org Delivered-To: mailing list commits@openwhisk.apache.org Received: (qmail 16245 invoked by uid 99); 4 Oct 2018 07:55:48 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 04 Oct 2018 07:55:48 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id 4F7ED85AE8; Thu, 4 Oct 2018 07:55:48 +0000 (UTC) Date: Thu, 04 Oct 2018 07:55:47 +0000 To: "commits@openwhisk.apache.org" Subject: [incubator-openwhisk] branch master updated: Improve splunk query (#4047) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <153863974767.16384.16025058362003083209@gitbox.apache.org> From: chetanm@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: incubator-openwhisk X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: bbe69aa13fd7bd7fd04d6dc2a67f2bc1cc1e2ee8 X-Git-Newrev: 27a624ecc763bc01eaa997ba9ce5fc55ad748221 X-Git-Rev: 27a624ecc763bc01eaa997ba9ce5fc55ad748221 X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated This is an automated email from the ASF dual-hosted git repository. chetanm pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git The following commit(s) were added to refs/heads/master by this push: new 27a624e Improve splunk query (#4047) 27a624e is described below commit 27a624ecc763bc01eaa997ba9ce5fc55ad748221 Author: tysonnorris AuthorDate: Thu Oct 4 00:54:49 2018 -0700 Improve splunk query (#4047) Improves the Splunk query and log format * Log is now formatted similar to DockerToActivationLogStore * Query time offset is made configurable to account for log collection delays --- common/scala/src/main/resources/application.conf | 18 ++++++++++++++++++ .../core/containerpool/logging/SplunkLogStore.scala | 18 ++++++++++++++---- .../containerpool/logging/SplunkLogStoreTests.scala | 20 ++++++++++++++------ 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/common/scala/src/main/resources/application.conf b/common/scala/src/main/resources/application.conf index b2bcbc6..712b3ef 100644 --- a/common/scala/src/main/resources/application.conf +++ b/common/scala/src/main/resources/application.conf @@ -209,6 +209,24 @@ whisk { teardown-on-exit = true //set to true to disable the mesos framework on system exit; set for false for HA deployments } + logstore { + #SplunkLogStore configuration + #splunk { + # host = "splunkhost" #splunk api hostname + # port = 8089 #splunk api port + # username = "splunkapiusername" #splunk api username + # password = "splunkapipassword" #splunk api password + # index = "splunkindex" #splunk index name + # log-timestamp-field = "log_timestamp" #splunk field where timestamp is stored (to reflect log event generated time, not splunk's _time) + # log-stream-field = "log_stream" #splunk field where stream is stored (stdout/stderr) + # log-message-field = "log_message" #splunk field where log message is stored + # activation-id-field = "activation_id" #splunk field where activation id is stored + # query-constraints = "" #additional constraints for splunk queries + # query-timestamp-offset-seconds = "" #splunk query will be broadened by this 2*; e.g. "earliest_time=activation.start - offset" and "latest_time=activation.end + offset" + # disableSNI = false #if true, disables hostname validation and cert validation (in case splunk api endpoint is using a self signed cert) + #} + } + # tracing configuration tracing { cache-expiry = 30 seconds #how long to keep spans in cache. Set to appropriate value to trace long running requests diff --git a/common/scala/src/main/scala/whisk/core/containerpool/logging/SplunkLogStore.scala b/common/scala/src/main/scala/whisk/core/containerpool/logging/SplunkLogStore.scala index 1cd93b5..f22ce33 100644 --- a/common/scala/src/main/scala/whisk/core/containerpool/logging/SplunkLogStore.scala +++ b/common/scala/src/main/scala/whisk/core/containerpool/logging/SplunkLogStore.scala @@ -60,8 +60,12 @@ case class SplunkLogStoreConfig(host: String, username: String, password: String, index: String, + logTimestampField: String, + logStreamField: String, logMessageField: String, activationIdField: String, + queryConstraints: String, + queryTimestampOffsetSeconds: Int, disableSNI: Boolean) case class SplunkResponse(results: Vector[JsObject]) object SplunkResponseJsonProtocol extends DefaultJsonProtocol { @@ -106,16 +110,18 @@ class SplunkLogStore( // {"preview":false,"init_offset":0,"messages":[],"fields":[{"name":"log_message"}],"results":[{"log_message":"some log message"}], "highlighted":{}} //note: splunk returns results in reverse-chronological order, therefore we include "| reverse" to cause results to arrive in chronological order val search = - s"""search index="${splunkConfig.index}"| spath ${splunkConfig.activationIdField}| search ${splunkConfig.activationIdField}=${activation.activationId.toString}| table ${splunkConfig.logMessageField}| reverse""" + s"""search index="${splunkConfig.index}"| spath ${splunkConfig.activationIdField}| search ${splunkConfig.queryConstraints} ${splunkConfig.activationIdField}=${activation.activationId.toString}| table ${splunkConfig.logTimestampField}, ${splunkConfig.logStreamField}, ${splunkConfig.logMessageField}| reverse""" val entity = FormData( Map( "exec_mode" -> "oneshot", "search" -> search, "output_mode" -> "json", - "earliest_time" -> activation.start.toString, //assume that activation start/end are UTC zone, and splunk events are the same + "earliest_time" -> activation.start + .minusSeconds(splunkConfig.queryTimestampOffsetSeconds) + .toString, //assume that activation start/end are UTC zone, and splunk events are the same "latest_time" -> activation.end - .plusSeconds(5) //add 5s to avoid a timerange of 0 on short-lived activations + .plusSeconds(splunkConfig.queryTimestampOffsetSeconds) //add 5s to avoid a timerange of 0 on short-lived activations .toString)).toEntity logging.debug(this, "sending request") @@ -130,7 +136,11 @@ class SplunkLogStore( .map(r => { ActivationLogs( r.results - .map(_.fields(splunkConfig.logMessageField).convertTo[String])) + .map(l => + //format same as whisk.core.containerpool.logging.LogLine.toFormattedString + f"${l.fields(splunkConfig.logTimestampField).convertTo[String]}%-30s ${l + .fields(splunkConfig.logStreamField) + .convertTo[String]}: ${l.fields(splunkConfig.logMessageField).convertTo[String].trim}")) }) }) } diff --git a/tests/src/test/scala/whisk/core/containerpool/logging/SplunkLogStoreTests.scala b/tests/src/test/scala/whisk/core/containerpool/logging/SplunkLogStoreTests.scala index dae47e6..c7d2935 100644 --- a/tests/src/test/scala/whisk/core/containerpool/logging/SplunkLogStoreTests.scala +++ b/tests/src/test/scala/whisk/core/containerpool/logging/SplunkLogStoreTests.scala @@ -60,15 +60,20 @@ class SplunkLogStoreTests "splunk-user", "splunk-pass", "splunk-index", + "log_timestamp", + "log_stream", "log_message", "activation_id", + "somefield::somevalue", + 22, disableSNI = false) behavior of "Splunk LogStore" val startTime = "2007-12-03T10:15:30Z" + val startTimePlusOffset = "2007-12-03T10:15:08Z" //queried end time range is endTime-22 val endTime = "2007-12-03T10:15:45Z" - val endTimePlus5 = "2007-12-03T10:15:50Z" //queried end time range is endTime+5 + val endTimePlusOffset = "2007-12-03T10:16:07Z" //queried end time range is endTime+22 val uuid = UUID() val user = Identity(Subject(), Namespace(EntityName("testSpace"), uuid), BasicAuthenticationAuthKey(uuid, Secret()), Set.empty) @@ -110,12 +115,12 @@ class SplunkLogStoreTests request.uri.path.toString() shouldBe "/services/search/jobs" request.headers shouldBe List(Authorization.basic(testConfig.username, testConfig.password)) - earliestTime shouldBe Some(startTime) - latestTime shouldBe Some(endTimePlus5) + earliestTime shouldBe Some(startTimePlusOffset) + latestTime shouldBe Some(endTimePlusOffset) outputMode shouldBe Some("json") execMode shouldBe Some("oneshot") search shouldBe Some( - s"""search index="${testConfig.index}"| spath ${testConfig.activationIdField}| search ${testConfig.activationIdField}=${activation.activationId.toString}| table ${testConfig.logMessageField}| reverse""") + s"""search index="${testConfig.index}"| spath ${testConfig.activationIdField}| search ${testConfig.queryConstraints} ${testConfig.activationIdField}=${activation.activationId.toString}| table ${testConfig.logTimestampField}, ${testConfig.logStreamField}, ${testConfig.logMessageField}| reverse""") ( Success( @@ -123,7 +128,7 @@ class SplunkLogStoreTests StatusCodes.OK, entity = HttpEntity( ContentTypes.`application/json`, - """{"preview":false,"init_offset":0,"messages":[],"fields":[{"name":"log_message"}],"results":[{"log_message":"some log message"},{"log_message":"some other log message"}], "highlighted":{}}"""))), + """{"preview":false,"init_offset":0,"messages":[],"fields":[{"name":"log_message"}],"results":[{"log_timestamp": "2007-12-03T10:15:30Z", "log_stream":"stdout", "log_message":"some log message"},{"log_timestamp": "2007-12-03T10:15:31Z", "log_stream":"stderr", "log_message":"some other log message"}], "highlighted":{}}"""))), userContext) } .recover { @@ -148,7 +153,10 @@ class SplunkLogStoreTests //use the a flow that asserts the request structure and provides a response in the expected format val splunkStore = new SplunkLogStore(system, Some(testFlow), testConfig) val result = await(splunkStore.fetchLogs(activation, context)) - result shouldBe ActivationLogs(Vector("some log message", "some other log message")) + result shouldBe ActivationLogs( + Vector( + "2007-12-03T10:15:30Z stdout: some log message", + "2007-12-03T10:15:31Z stderr: some other log message")) } it should "fail to connect to bogus host" in {