All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.atlas.lwc.events.ExprUtils.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014-2024 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.lwc.events

import com.netflix.atlas.core.model.DataExpr
import com.netflix.atlas.core.model.DataVocabulary
import com.netflix.atlas.core.model.EventExpr
import com.netflix.atlas.core.model.EventVocabulary
import com.netflix.atlas.core.model.ModelExtractors
import com.netflix.atlas.core.model.Query
import com.netflix.atlas.core.model.TraceQuery
import com.netflix.atlas.core.model.TraceVocabulary
import com.netflix.atlas.core.stacklang.Interpreter
import com.netflix.spectator.atlas.impl.Parser

/**
  * Helper functions for working with expressions.
  */
private[events] object ExprUtils {

  import ModelExtractors.*

  private val dataInterpreter = Interpreter(DataVocabulary.allWords)

  /** Parse a single data expression. */
  def parseDataExpr(str: String): DataExpr = {
    dataInterpreter.execute(str).stack match {
      case DataExprType(e) :: Nil => e
      case _                      => throw new IllegalArgumentException(str)
    }
  }

  private val eventInterpreter = Interpreter(EventVocabulary.allWords)

  /** Parse a single event expression. */
  def parseEventExpr(str: String): EventExpr = {
    eventInterpreter.execute(str).stack match {
      case EventExprType(e) :: Nil => e
      case _                       => throw new IllegalArgumentException(str)
    }
  }

  private val traceInterpreter = Interpreter(TraceVocabulary.allWords)

  /** Parse a single trace events query expression. */
  def parseTraceEventsQuery(str: String): TraceQuery.SpanFilter = {
    traceInterpreter.execute(str).stack match {
      case TraceFilterType(tq) :: Nil => tq
      case _                          => throw new IllegalArgumentException(str)
    }
  }

  /** Parse a single trace time series query expression. */
  def parseTraceTimeSeriesQuery(str: String): TraceQuery.SpanTimeSeries = {
    traceInterpreter.execute(str).stack match {
      case TraceTimeSeriesType(tq) :: Nil => tq
      case _                              => throw new IllegalArgumentException(str)
    }
  }

  /** Convert from Atlas query model to Spectator to use with a QueryIndex. */
  def toSpectatorQuery(query: Query): SpectatorQuery = {
    Parser.parseQuery(query.toString)
  }

  /**
    * Check if a query matches based on tags provided by a function.
    *
    * @param query
    *     Query to use for matching against the set of tags.
    * @param tags
    *     Function that returns the value for a given key. If there is no mapping
    *     for a given key, then it should return `null`.
    */
  def matches(query: Query, tags: String => String): Boolean = {
    query match {
      case Query.True             => true
      case Query.False            => false
      case q: Query.HasKey        => tags(q.k) != null
      case q: Query.KeyValueQuery => check(q, tags)
      case Query.And(q1, q2)      => matches(q1, tags) && matches(q2, tags)
      case Query.Or(q1, q2)       => matches(q1, tags) || matches(q2, tags)
      case Query.Not(q)           => !matches(q, tags)
    }
  }

  private def check(q: Query.KeyValueQuery, tags: String => String): Boolean = {
    val v = tags(q.k)
    v != null && q.check(v)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy