1*46c4c49dSIbrahim Kanouche// Copyright 2020 Google Inc. 2*46c4c49dSIbrahim Kanouche// 3*46c4c49dSIbrahim Kanouche// Licensed under the Apache License, Version 2.0 (the "License"); 4*46c4c49dSIbrahim Kanouche// you may not use this file except in compliance with the License. 5*46c4c49dSIbrahim Kanouche// You may obtain a copy of the License at 6*46c4c49dSIbrahim Kanouche// 7*46c4c49dSIbrahim Kanouche// http://www.apache.org/licenses/LICENSE-2.0 8*46c4c49dSIbrahim Kanouche// 9*46c4c49dSIbrahim Kanouche// Unless required by applicable law or agreed to in writing, software 10*46c4c49dSIbrahim Kanouche// distributed under the License is distributed on an "AS IS" BASIS, 11*46c4c49dSIbrahim Kanouche// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*46c4c49dSIbrahim Kanouche// See the License for the specific language governing permissions and 13*46c4c49dSIbrahim Kanouche// limitations under the License. 14*46c4c49dSIbrahim Kanouche 15*46c4c49dSIbrahim Kanouchepackage classifier 16*46c4c49dSIbrahim Kanouche 17*46c4c49dSIbrahim Kanoucheimport ( 18*46c4c49dSIbrahim Kanouche "fmt" 19*46c4c49dSIbrahim Kanouche "strings" 20*46c4c49dSIbrahim Kanouche) 21*46c4c49dSIbrahim Kanouche 22*46c4c49dSIbrahim Kanouche// This file contains routines for a simple trace execution mechanism. 23*46c4c49dSIbrahim Kanouche 24*46c4c49dSIbrahim Kanouche// TraceConfiguration specifies the configuration for tracing execution of the 25*46c4c49dSIbrahim Kanouche// license classifier. 26*46c4c49dSIbrahim Kanouchetype TraceConfiguration struct { 27*46c4c49dSIbrahim Kanouche // Comma-separated list of phases to be traced. Can use * for all phases. 28*46c4c49dSIbrahim Kanouche TracePhases string 29*46c4c49dSIbrahim Kanouche // Comma-separated list of licenses to be traced. Can use * as a suffix to 30*46c4c49dSIbrahim Kanouche // match prefixes, or by itself to match all licenses. 31*46c4c49dSIbrahim Kanouche TraceLicenses string 32*46c4c49dSIbrahim Kanouche 33*46c4c49dSIbrahim Kanouche // Tracer specifies a TraceFunc used to capture tracing information. 34*46c4c49dSIbrahim Kanouche // If not supplied, emits using fmt.Printf 35*46c4c49dSIbrahim Kanouche Tracer TraceFunc 36*46c4c49dSIbrahim Kanouche tracePhases map[string]bool 37*46c4c49dSIbrahim Kanouche traceLicenses map[string]bool 38*46c4c49dSIbrahim Kanouche} 39*46c4c49dSIbrahim Kanouche 40*46c4c49dSIbrahim Kanouchefunc (t *TraceConfiguration) init() { 41*46c4c49dSIbrahim Kanouche if t == nil { 42*46c4c49dSIbrahim Kanouche return 43*46c4c49dSIbrahim Kanouche } 44*46c4c49dSIbrahim Kanouche // Sample the config values to create the lookup maps 45*46c4c49dSIbrahim Kanouche t.traceLicenses = make(map[string]bool) 46*46c4c49dSIbrahim Kanouche t.tracePhases = make(map[string]bool) 47*46c4c49dSIbrahim Kanouche 48*46c4c49dSIbrahim Kanouche if len(t.TraceLicenses) > 0 { 49*46c4c49dSIbrahim Kanouche for _, lic := range strings.Split(t.TraceLicenses, ",") { 50*46c4c49dSIbrahim Kanouche t.traceLicenses[lic] = true 51*46c4c49dSIbrahim Kanouche } 52*46c4c49dSIbrahim Kanouche } 53*46c4c49dSIbrahim Kanouche 54*46c4c49dSIbrahim Kanouche if len(t.TracePhases) > 0 { 55*46c4c49dSIbrahim Kanouche for _, phase := range strings.Split(t.TracePhases, ",") { 56*46c4c49dSIbrahim Kanouche t.tracePhases[phase] = true 57*46c4c49dSIbrahim Kanouche } 58*46c4c49dSIbrahim Kanouche } 59*46c4c49dSIbrahim Kanouche} 60*46c4c49dSIbrahim Kanouche 61*46c4c49dSIbrahim Kanouchevar traceLicenses map[string]bool 62*46c4c49dSIbrahim Kanouchevar tracePhases map[string]bool 63*46c4c49dSIbrahim Kanouche 64*46c4c49dSIbrahim Kanouchefunc (t *TraceConfiguration) shouldTrace(phase string) bool { 65*46c4c49dSIbrahim Kanouche if t == nil { 66*46c4c49dSIbrahim Kanouche return false 67*46c4c49dSIbrahim Kanouche } 68*46c4c49dSIbrahim Kanouche if t.tracePhases["*"] { 69*46c4c49dSIbrahim Kanouche return true 70*46c4c49dSIbrahim Kanouche } 71*46c4c49dSIbrahim Kanouche return t.tracePhases[phase] 72*46c4c49dSIbrahim Kanouche} 73*46c4c49dSIbrahim Kanouche 74*46c4c49dSIbrahim Kanouchefunc (t *TraceConfiguration) isTraceLicense(lic string) bool { 75*46c4c49dSIbrahim Kanouche if t == nil { 76*46c4c49dSIbrahim Kanouche return false 77*46c4c49dSIbrahim Kanouche } 78*46c4c49dSIbrahim Kanouche if t.traceLicenses[lic] { 79*46c4c49dSIbrahim Kanouche return true 80*46c4c49dSIbrahim Kanouche } 81*46c4c49dSIbrahim Kanouche 82*46c4c49dSIbrahim Kanouche for e := range t.traceLicenses { 83*46c4c49dSIbrahim Kanouche if idx := strings.Index(e, "*"); idx != -1 { 84*46c4c49dSIbrahim Kanouche if strings.HasPrefix(lic, e[0:idx]) { 85*46c4c49dSIbrahim Kanouche return true 86*46c4c49dSIbrahim Kanouche } 87*46c4c49dSIbrahim Kanouche } 88*46c4c49dSIbrahim Kanouche } 89*46c4c49dSIbrahim Kanouche 90*46c4c49dSIbrahim Kanouche return false 91*46c4c49dSIbrahim Kanouche} 92*46c4c49dSIbrahim Kanouche 93*46c4c49dSIbrahim Kanouchefunc (t *TraceConfiguration) trace(f string, args ...interface{}) { 94*46c4c49dSIbrahim Kanouche if t == nil || t.Tracer == nil { 95*46c4c49dSIbrahim Kanouche fmt.Printf(f, args...) 96*46c4c49dSIbrahim Kanouche fmt.Println() 97*46c4c49dSIbrahim Kanouche return 98*46c4c49dSIbrahim Kanouche } 99*46c4c49dSIbrahim Kanouche 100*46c4c49dSIbrahim Kanouche t.Tracer(f, args...) 101*46c4c49dSIbrahim Kanouche} 102*46c4c49dSIbrahim Kanouche 103*46c4c49dSIbrahim Kanouchefunc (t *TraceConfiguration) traceSearchset(lic string) bool { 104*46c4c49dSIbrahim Kanouche return t.isTraceLicense(lic) && t.shouldTrace("searchset") 105*46c4c49dSIbrahim Kanouche} 106*46c4c49dSIbrahim Kanouche 107*46c4c49dSIbrahim Kanouchefunc (t *TraceConfiguration) traceTokenize(lic string) bool { 108*46c4c49dSIbrahim Kanouche return t.isTraceLicense(lic) && t.shouldTrace("tokenize") 109*46c4c49dSIbrahim Kanouche} 110*46c4c49dSIbrahim Kanouche 111*46c4c49dSIbrahim Kanouchefunc (t *TraceConfiguration) traceScoring(lic string) bool { 112*46c4c49dSIbrahim Kanouche return t.isTraceLicense(lic) && t.shouldTrace("score") 113*46c4c49dSIbrahim Kanouche} 114*46c4c49dSIbrahim Kanouche 115*46c4c49dSIbrahim Kanouchefunc (t *TraceConfiguration) traceFrequency(lic string) bool { 116*46c4c49dSIbrahim Kanouche return t.isTraceLicense(lic) && t.shouldTrace("frequency") 117*46c4c49dSIbrahim Kanouche} 118*46c4c49dSIbrahim Kanouche 119*46c4c49dSIbrahim Kanouche// TraceFunc works like fmt.Printf to emit tracing data for the 120*46c4c49dSIbrahim Kanouche// classifier. 121*46c4c49dSIbrahim Kanouchetype TraceFunc func(string, ...interface{}) 122