Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lwcapi merge #459

Merged
merged 178 commits into from
Dec 2, 2016
Merged
Show file tree
Hide file tree
Changes from 162 commits
Commits
Show all changes
178 commits
Select commit Hold shift + click to select a range
9d83204
add dependency for redisclient
Aug 16, 2016
cb323a0
add lwcapi build
Aug 16, 2016
36f71ef
add lwcapi
Aug 16, 2016
d909eac
tag messages with a uuid to avoid doing double work
Aug 16, 2016
343bb45
add license header
Aug 17, 2016
500d3ec
clean up actor structure
Aug 17, 2016
5f29867
brute-force reconnect after 1 second. Needs improving.
Aug 17, 2016
d6b951b
catch exceptions, and retry. Now starts properly even when redis is …
Aug 17, 2016
e3cedde
print error on connect. Factor out 'catch safely'
Aug 17, 2016
f8378e1
add a few more exceptions to never catch
Aug 17, 2016
5722152
accept URI path segments for the cluster name
skandragon Aug 19, 2016
249a2b7
reformat paths, and make consistent across all our routes
Aug 22, 2016
5728a06
simple tests
Aug 22, 2016
c8f098f
simplify
Aug 22, 2016
04c112a
catch unmatched state and throw
Aug 22, 2016
40fc240
change what we send
Aug 22, 2016
cb98108
use Datapoint for data submissions
skandragon Aug 23, 2016
830d336
add redis-server
skandragon Aug 24, 2016
2f79b95
set my maven repo for builds
Aug 24, 2016
dbced2f
force publish only to bintray
Aug 24, 2016
cc70713
disable tests for now
Aug 24, 2016
a6346d0
make snapshot do a release instead
Aug 24, 2016
e7f601b
depend on and install Akka
Aug 24, 2016
f30e71b
fix syntax
Aug 24, 2016
0a898e6
inject Registry
Aug 24, 2016
d55e729
add concept of a cluster to all requests
Aug 25, 2016
7867056
Revert "make snapshot do a release instead"
Aug 25, 2016
fd7cfcb
rework publish disable
Aug 25, 2016
1adde74
disable snapshot bintray uploads
Aug 25, 2016
db46730
disable bintray in a better way
Aug 25, 2016
56026ca
also check cluster is parsed properly
Aug 25, 2016
0c3f7e0
enable tests, disable publish here once and for all
Aug 25, 2016
d47ab77
remove cluster as we can derive it later
Aug 26, 2016
bd68086
return the real calculation, not 1
Aug 26, 2016
76de29f
start using QueryIndex
Aug 29, 2016
a24ac56
add testing scripts
Aug 29, 2016
4006d01
new output format, clean up tests
Sep 1, 2016
f9863f2
Render json to the journal
Sep 1, 2016
00b6331
compute filename and expiry from the same timestamp
Sep 1, 2016
dfee9d0
spectator instrumentation
Sep 2, 2016
a2670ea
'type' tag -> 'action'
Sep 2, 2016
8fbbfe0
add .DS_Store
skandragon Sep 6, 2016
c21038e
reset tests
skandragon Sep 6, 2016
5a01bc6
automatically simplify matching expressions
Sep 7, 2016
4ce3a75
no longer need cluster here
Sep 8, 2016
c503f15
limit the set of tag keys to exactly what we need
Sep 8, 2016
12c57de
start to use a query index
Sep 8, 2016
9a332dc
refactor to store queries and expressions in a more useful structure
skandragon Sep 9, 2016
0ce9371
filter based on cluster contest
skandragon Sep 9, 2016
b790ade
make an actual map
skandragon Sep 9, 2016
eb47491
refactor to use ConcurrentHashMap
Sep 12, 2016
d33059f
publish everything again
Sep 12, 2016
b9edbfa
add a test for same expr, different frequencies
Sep 12, 2016
6ef570a
return data expressions sorted
Sep 12, 2016
f876900
add license header
Sep 12, 2016
f980d15
use base-64 sha1 for keys
Sep 12, 2016
d99c8eb
clean up API
Sep 12, 2016
4575013
clean up imports
Sep 12, 2016
a6bcae2
accept eval requests, and return a JSON status for each
Sep 12, 2016
1ec3326
clean up
skandragon Sep 13, 2016
9668e50
define ttl and expr-key-prefix defaults
skandragon Sep 13, 2016
ad913ed
return the key for the expression set
skandragon Sep 13, 2016
9a91d2d
write and load all expressions from redis on startup
skandragon Sep 13, 2016
20e5406
fix tests
skandragon Sep 13, 2016
515d099
sample evaluate json
Sep 13, 2016
dc3a5ba
remove frequency, change failed report to a Map
skandragon Sep 13, 2016
49452ac
start on subscription endpoint
skandragon Sep 14, 2016
6a48fc3
apply(String) -> fromJson(String), and simplify toJson where we can
Sep 14, 2016
62ccfa6
return empty strings for data expressions that a specific client cann…
Sep 14, 2016
80f6f0e
switch to url-safe base64 encoding without padding
Sep 14, 2016
c555ecc
clean up json conversion
Sep 14, 2016
0548968
record acks
Sep 15, 2016
d0d2516
send without acks here
Sep 15, 2016
f102e9f
sse streams almost work
Sep 16, 2016
efff22f
refactor to generate the id once
Sep 16, 2016
a6aa0db
complete refactor
Sep 16, 2016
d400404
remove split(string, long)
Sep 16, 2016
288529d
make interner private to each splitter
Sep 19, 2016
9495592
inject ExpressionSplitterImpl -> ExpresionSplitter so we use the same…
Sep 19, 2016
8180f3c
remove unneeded argument
Sep 19, 2016
c0d7619
inject AlertMapImpl() for AlertMap()
Sep 19, 2016
9a3504f
refactor SSEActor
Sep 19, 2016
887722b
alter subscription manager to maintin a list of ssId => expressionId …
Sep 19, 2016
93008d8
comment
Sep 19, 2016
bb529ad
data flows almost work
Sep 20, 2016
bab4580
bump heartbeating to 30 seconds of no activity
skandragon Sep 20, 2016
d54013f
SessionManager holds all sse state
skandragon Sep 20, 2016
715d6d5
change sse endpoint to stream
skandragon Sep 20, 2016
7323f7d
remove lock and extra junk from TestActor
skandragon Sep 20, 2016
12a5823
refactor class name to match endpoint name
skandragon Sep 20, 2016
d143130
remove specific 2.11 reference
skandragon Sep 20, 2016
44e3e5d
expand test coverage
skandragon Sep 20, 2016
99db2e7
add ApiSettings tests, and remove unneeded code
skandragon Sep 20, 2016
19723aa
more tests
skandragon Sep 21, 2016
c98c065
actor test using home-grown framework
skandragon Sep 21, 2016
98a4b8e
rename refactoring
skandragon Sep 21, 2016
b955f4d
make streamId required
skandragon Sep 21, 2016
102e396
remove redundant test
skandragon Sep 21, 2016
8edee5d
clean up imports
Sep 21, 2016
972eb08
clean up imports
Sep 21, 2016
da1265f
change telemetry tag
Sep 21, 2016
b06f5a9
a test for our custom toString()
Sep 21, 2016
383a011
fix sending of BoxedUnit on accident
Sep 21, 2016
b996a64
rename redis expression key prefix
Sep 21, 2016
89426be
stop throwing exceptions, just connect things as best we can
Sep 21, 2016
4c4dade
Rename sse to stream
Sep 21, 2016
f7f3d27
refactor to keep a better organized database
Sep 21, 2016
8fd4606
refactor redis to be expression add, subscribe, and unsubscribe
Sep 22, 2016
dcb746f
make a note about loading subscriptions
Sep 22, 2016
d74e756
start on ttl-based expiry
Sep 22, 2016
f0440f3
expand strings
Sep 22, 2016
7873890
move loading to database actor
Sep 22, 2016
343f2d8
add in a database service that just sets healthcheck if we are fully …
Sep 23, 2016
5842ba4
fix url
Sep 23, 2016
bc7bf1e
stop premature interning
Sep 23, 2016
4079693
use the service to indicate our health
Sep 23, 2016
8b7306e
allow running two instances for real
Sep 24, 2016
e7f9127
fix exprId
Sep 24, 2016
666af9f
fully implement TTL-based expression tracking
Sep 24, 2016
16503d3
shut down existing connections with the same streamId
Sep 24, 2016
42c3dbe
fix up to avoid a race condition
Sep 24, 2016
c746c4d
make subscribe actually work
skandragon Sep 24, 2016
bd52ffc
add jitter and add a :::redis endpoint to monitor redis traffic over sse
skandragon Sep 24, 2016
94116ca
only jitter forward
skandragon Sep 24, 2016
aa22484
use injected registry
skandragon Sep 24, 2016
fe9488b
add more debug logging to track down a db issue
skandragon Sep 24, 2016
b9c9237
fix app name
skandragon Sep 25, 2016
a59207d
start working on queryindex debugging
skandragon Sep 25, 2016
fffc5a1
remove my test
skandragon Sep 25, 2016
4a37938
report instance and uuid, mostly for debugging
skandragon Sep 25, 2016
b133e01
add more identifying info to hello messages
skandragon Sep 25, 2016
0452db7
normalize ids
Sep 26, 2016
1363d6d
more metrics for all actors
Sep 26, 2016
5623898
actually increment
Sep 26, 2016
cd58f23
simplify
skandragon Sep 27, 2016
f56b826
rework json such that each expression stands on its own
skandragon Sep 28, 2016
40c7f1d
catch strings rather than numbers
Sep 28, 2016
4820b5d
start using the default option serializer
Sep 29, 2016
8943114
disable some tests for now
Sep 29, 2016
9f0f420
tweak ttl
Sep 29, 2016
557db2a
adjust error messages, fix jitter
Sep 29, 2016
f47bd7c
adjust jitter, take 99
Sep 29, 2016
dc7bf00
Rename
Sep 30, 2016
ac8616e
new json code
Oct 3, 2016
9e711a4
add methods to add and remove the redis prefix, if any is set
Oct 5, 2016
d71f044
fix prefix when empty string
Oct 5, 2016
ecdba60
rename service to be more descriptive
Oct 5, 2016
f152279
normalize terms used in json
Oct 6, 2016
8590261
normalize expression return
Oct 6, 2016
d992766
update sample data and scripts
Oct 6, 2016
b41b5ea
include instanceId in the heartbeat messages
Oct 7, 2016
9e65284
normalize redis logging and publishing to always increment stats prop…
Oct 7, 2016
b4d221b
lock down redis publish to only accept classes with our trait
Oct 7, 2016
ff6d2a9
add a counter to track number of stream sessions
Oct 7, 2016
0b5ac75
add a tag
Oct 7, 2016
3e1fb02
if there is a post body when a new stream is set up, subscribe throug…
Nov 7, 2016
0dd36e2
refactor to not require a StreamId on subscribe-via-stream-request
Nov 10, 2016
50cad0c
make it right, as what we were doing would not work
Nov 10, 2016
56ceff6
clean up
Nov 10, 2016
6c33206
change exception expected
Nov 10, 2016
d61dcd4
directly subscribe, don't use the subscription actor just yet
Nov 11, 2016
0292985
prepare for PR
skandragon Nov 21, 2016
673b8f0
use getDuration
skandragon Dec 1, 2016
1a7db39
use an include
skandragon Dec 1, 2016
10a790c
use duration format
skandragon Dec 1, 2016
c2bed30
fix fallout of converting to getDuration
skandragon Dec 1, 2016
f6eb7e9
remove spectatorSandbox
skandragon Dec 1, 2016
001d936
move some vals from class to object
skandragon Dec 1, 2016
ce4eab0
resolve comments on ExpressionDatabaseActor
skandragon Dec 1, 2016
9a0e7b5
fix up ExpressionDatabaseImpl based on review feedback
skandragon Dec 1, 2016
4b4f6a8
remove duplicate logging
skandragon Dec 1, 2016
153e49f
remove default debug logging
skandragon Dec 1, 2016
c0069f6
fix provides
skandragon Dec 1, 2016
afb28ae
address remaining comments
skandragon Dec 1, 2016
b07299a
add comment
skandragon Dec 1, 2016
143dc72
adjust based on comments
skandragon Dec 1, 2016
6e9a4fb
adjust based on feedback
skandragon Dec 1, 2016
b4e9a2b
use thingCount consistently
skandragon Dec 2, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ cache:
directories:
- $HOME/.sbt
- $HOME/.ivy2
services:
- redis-server
38 changes: 38 additions & 0 deletions atlas-lwcapi/src/main/resources/reference.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
atlas {
lwcapi {
register = {
default-frequency = 60000
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use duration format so it is easier to read and the unit is explicit.

}

redis = {
host = "localhost"
port = 6379
ttl = 300000 // in milliseconds, default 5 minutes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment on duration format.

prefix = "" // default empty (could be omitted)
}
}

akka {
actors = ${?atlas.akka.actors} [
{
name = "lwc.expressiondb"
class = "com.netflix.atlas.lwcapi.ExpressionDatabaseActor"
},
{
name = "lwc.subscribe"
class = "com.netflix.atlas.lwcapi.SubscribeActor"
},
{
name = "lwc.evaluate"
class = "com.netflix.atlas.lwcapi.EvaluateActor"
}
]

api-endpoints = ${?atlas.akka.api-endpoints} [
"com.netflix.atlas.lwcapi.EvaluateApi",
"com.netflix.atlas.lwcapi.ExpressionApi",
"com.netflix.atlas.lwcapi.SubscribeApi",
"com.netflix.atlas.lwcapi.StreamApi"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2014-2016 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.atlas.lwcapi

import com.netflix.atlas.config.ConfigManager
import com.typesafe.config.Config

object ApiSettings extends ApiSettings(ConfigManager.current)

class ApiSettings(root: => Config) {
private def config = root.getConfig("atlas.lwcapi")

def defaultFrequency: Int = config.getInt("register.default-frequency")

def redisHost: String = config.getString("redis.host")
def redisPort: Int = config.getInt("redis.port")
def redisTTL: Int = config.getInt("redis.ttl")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

def redisPrefix: String = {
if (config.hasPath("redis.prefix")) {
if (config.getString("redis.prefix").nonEmpty)
config.getString("redis.prefix") + "."
else
""
} else ""
}

def redisPrefixFor(suffix: String): String = {
s"$redisPrefix$suffix"
}

def stripRedisPrefix(s: String): String = {
if (redisPrefix.isEmpty) s else s.stripPrefix(redisPrefix)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2014-2016 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.atlas.lwcapi

import javax.inject.Singleton

import com.netflix.iep.service.{AbstractService, State}
import com.typesafe.scalalogging.StrictLogging

@Singleton
class DatabaseService extends AbstractService with StrictLogging {
@volatile private var started = false

def setState(value: Boolean): Unit = started = value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Locally to this class, it seems odd to have setState modify the started variable when there is another state variable in scope.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought "state" was the state of the registration, while "started" really means "initial transfer from other instances via redis is complete"

I can rename things to to make it clearer, and add commends, unless I really can / should touch "state" here.


override def isHealthy: Boolean = state == State.RUNNING && started

override def startImpl(): Unit = {
logger.info("Starting Database service monitor")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lifecycle manager will already have logs for calling the start/stop, e.g.:

https://github.com/Netflix/iep/blob/master/iep-guice/src/main/java/com/netflix/iep/guice/AnnotationUtils.java#L55

}

override def stopImpl(): Unit = {
logger.info("Stopping Database service monitor")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2014-2016 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.atlas.lwcapi

import javax.inject.Inject

import akka.actor.{Actor, ActorLogging}
import com.netflix.atlas.akka.DiagnosticMessage
import com.netflix.atlas.lwcapi.StreamApi._
import com.netflix.spectator.api.Registry
import spray.http.{HttpResponse, StatusCodes}

class EvaluateActor @Inject() (registry: Registry, sm: SubscriptionManager) extends Actor with ActorLogging {
import com.netflix.atlas.lwcapi.EvaluateApi._

private val evalsId = registry.createId("atlas.lwcapi.evaluate.count")
private val itemsId = registry.createId("atlas.lwcapi.evaluate.itemCount")
private val actorsId = registry.createId("atlas.lwcapi.evaluate.actorCount")
private val uninterestingId = registry.createId("atlas.lwcapi.evaluate.uninterestingCount")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in some other places we tend to call these "ignored".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix.


def receive = {
case EvaluateRequest(_, Nil) =>
DiagnosticMessage.sendError(sender(), StatusCodes.BadRequest, "empty expression payload")
case EvaluateRequest(timestamp, items) =>
evaluate(timestamp, items)
sender() ! HttpResponse(StatusCodes.OK)
case _ =>
DiagnosticMessage.sendError(sender(), StatusCodes.BadRequest, "unknown payload")
}

private def evaluate(timestamp: Long, items: List[Item]): Unit = {
registry.counter(evalsId).increment()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you aren't adding any additional tags, it would be better to cache the counter as the class member variable. It avoids looking up the id to find the counter. Lookups are fairly quick, but slower than just accessing a member variable.

registry.counter(itemsId).increment(items.size)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, that size on a list is linear.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I iterate over the list, I could increment a counter and update the metric at the end. Do you think this is necessary?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not too worried about it in this particular case, just mentioning in case there is an easy way to avoid it. I have seen things like size calls become pretty expensive in the past and it is often assumed it will be a constant time operation. When we start running it under more load we can deal with it if it shows up on a profile.

items.foreach { item =>
val actors = sm.actorsForExpression(item.id)
if (actors.nonEmpty) {
registry.counter(actorsId).increment(actors.size)
val message = SSEMetric(timestamp, item)
actors.foreach(actor => actor ! message)
} else {
registry.counter(uninterestingId).increment()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2014-2016 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.atlas.lwcapi

import akka.actor.ActorRefFactory
import com.netflix.atlas.akka.WebApi
import com.netflix.atlas.json.{Json, JsonSupport}
import com.netflix.atlas.lwcapi.StreamApi.SSEMessage
import spray.routing.RequestContext

class EvaluateApi(implicit val actorRefFactory: ActorRefFactory) extends WebApi {
import EvaluateApi._

private val evaluateRef = actorRefFactory.actorSelection("/user/lwc.evaluate")

def routes: RequestContext => Unit = {
path("lwc" / "api" / "v1" / "evaluate") {
post { ctx => handleReq(ctx) }
}
}

private def handleReq(ctx: RequestContext): Unit = {
val request = EvaluateRequest.fromJson(ctx.request.entity.asString)
evaluateRef.tell(request, ctx.responder)
}
}

object EvaluateApi {
type TagMap = Map[String, String]

case class Item(id: String, tags: TagMap, value: Double) extends JsonSupport

case class EvaluateRequest(timestamp: Long, metrics: List[Item]) extends JsonSupport
object EvaluateRequest {
def fromJson(json: String) = Json.decode[EvaluateRequest](json)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2014-2016 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.atlas.lwcapi

import javax.inject.Inject

import akka.actor.ActorRefFactory
import com.netflix.atlas.akka.WebApi
import com.netflix.atlas.json.{Json, JsonSupport}
import com.netflix.spectator.api.Registry
import com.typesafe.scalalogging.StrictLogging
import spray.http.{HttpResponse, StatusCodes}
import spray.routing.RequestContext

case class ExpressionApi @Inject()(alertmap: ExpressionDatabase,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alert map name seems odd here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renaming issue from a long time ago.

registry: Registry,
implicit val actorRefFactory: ActorRefFactory)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer not to align with the opening paren, it creates a big gap and leads to unnecessary diffs with name changes.

extends WebApi with StrictLogging {
import ExpressionApi._

private val defaultURL = "http://..."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This appears to be unused.


private val expressionFetchesId = registry.createId("atlas.lwcapi.expressions.fetches")
private val expressionCount = registry.distributionSummary("atlas.lwcapi.expressions.count")

def routes: RequestContext => Unit = {
path("lwc" / "api" / "v1" / "expressions" / Segment) { (cluster) =>
get { ctx => handleReq(ctx, cluster) }
}
}

private def handleReq(ctx: RequestContext, cluster: String): Unit = {
val expressions = alertmap.expressionsForCluster(cluster)
val json = Return(expressions).toJson
ctx.responder ! HttpResponse(StatusCodes.OK, entity = json)
registry.counter(expressionFetchesId.withTag("cluster", cluster)).increment()
expressionCount.record(expressions.size)
}
}

object ExpressionApi {
case class Return(expressions: List[ExpressionWithFrequency]) extends JsonSupport
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2014-2016 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.atlas.lwcapi

import com.netflix.atlas.core.model.Query
import com.netflix.atlas.lwcapi.ExpressionSplitter.SplitResult

abstract class ExpressionDatabase {
def addExpr(expr: ExpressionWithFrequency, queries: Query): Boolean
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/queries/query/

def delExpr(id: String): Boolean
def hasExpr(id: String): Boolean
def expr(id: String): Option[ExpressionWithFrequency]
def expressionsForCluster(cluster: String): List[ExpressionWithFrequency]
}