Skip to content

Commit

Permalink
[mixer] Introduce tracespan template into Mixer (istio#1349)
Browse files Browse the repository at this point in the history
* Introduce tracespan template into Mixer

* Address review comments

* Add generated files
  • Loading branch information
douglas-reid authored and jamsajones committed Jan 3, 2018
1 parent 70834f8 commit df6649a
Show file tree
Hide file tree
Showing 8 changed files with 1,651 additions and 2 deletions.
2 changes: 2 additions & 0 deletions generated_files
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ mixer/template/sample/report/go_default_library_handler.gen.go
mixer/template/sample/report/go_default_library_tmpl.pb.go
mixer/template/sample/template.gen.go
mixer/template/template.gen.go
mixer/template/tracespan/go_default_library_handler.gen.go
mixer/template/tracespan/go_default_library_tmpl.pb.go
mixer/test/template/report/go_default_library_handler.gen.go
mixer/test/template/report/go_default_library_tmpl.pb.go
mixer/test/template/template.gen.go
Expand Down
2 changes: 2 additions & 0 deletions lintconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
"mixer/template/sample/report/go_default_library_tmpl.pb.go",
"mixer/template/sample/template.gen.go",
"mixer/template/template.gen.go",
"mixer/template/tracespan/go_default_library_handler.gen.go",
"mixer/template/tracespan/go_default_library_tmpl.pb.go",
"mixer/test/template/report/go_default_library_handler.gen.go",
"mixer/test/template/report/go_default_library_tmpl.pb.go",
"mixer/test/template/template.gen.go",
Expand Down
6 changes: 4 additions & 2 deletions mixer/template/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ load("//mixer/tools/codegen:generate.bzl", "mixer_supported_template_library")
mixer_supported_template_library(
name = "go_default_library",
packages = {
"//mixer/template/apikey:go_default_library_proto.descriptor_set": "istio.io/istio/mixer/template/apikey",
"//mixer/template/checknothing:go_default_library_proto.descriptor_set": "istio.io/istio/mixer/template/checknothing",
"//mixer/template/listentry:go_default_library_proto.descriptor_set": "istio.io/istio/mixer/template/listentry",
"//mixer/template/logentry:go_default_library_proto.descriptor_set": "istio.io/istio/mixer/template/logentry",
"//mixer/template/metric:go_default_library_proto.descriptor_set": "istio.io/istio/mixer/template/metric",
"//mixer/template/quota:go_default_library_proto.descriptor_set": "istio.io/istio/mixer/template/quota",
"//mixer/template/reportnothing:go_default_library_proto.descriptor_set": "istio.io/istio/mixer/template/reportnothing",
"//mixer/template/checknothing:go_default_library_proto.descriptor_set": "istio.io/istio/mixer/template/checknothing",
"//mixer/template/apikey:go_default_library_proto.descriptor_set": "istio.io/istio/mixer/template/apikey",
"//mixer/template/tracespan:go_default_library_proto.descriptor_set": "istio.io/istio/mixer/template/tracespan",
},
deps = [
"//mixer/template/apikey:go_default_library",
Expand All @@ -21,5 +22,6 @@ mixer_supported_template_library(
"//mixer/template/metric:go_default_library",
"//mixer/template/quota:go_default_library",
"//mixer/template/reportnothing:go_default_library",
"//mixer/template/tracespan:go_default_library",
],
)
192 changes: 192 additions & 0 deletions mixer/template/template.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ import (

"istio.io/istio/mixer/template/reportnothing"

"istio.io/istio/mixer/template/tracespan"

"time"
)

Expand Down Expand Up @@ -704,5 +706,195 @@ var (
return nil
},
},

tracespan.TemplateName: {
Name: tracespan.TemplateName,
Impl: "tracespan",
CtrCfg: &tracespan.InstanceParam{},
Variety: adptTmpl.TEMPLATE_VARIETY_REPORT,
BldrInterfaceName: tracespan.TemplateName + "." + "HandlerBuilder",
HndlrInterfaceName: tracespan.TemplateName + "." + "Handler",
BuilderSupportsTemplate: func(hndlrBuilder adapter.HandlerBuilder) bool {
_, ok := hndlrBuilder.(tracespan.HandlerBuilder)
return ok
},
HandlerSupportsTemplate: func(hndlr adapter.Handler) bool {
_, ok := hndlr.(tracespan.Handler)
return ok
},
InferType: func(cp proto.Message, tEvalFn template.TypeEvalFn) (proto.Message, error) {
var err error = nil
cpb := cp.(*tracespan.InstanceParam)
infrdType := &tracespan.Type{}

if cpb.TraceId == "" || cpb.TraceId == emptyQuotes {
return nil, errors.New("expression for field TraceId cannot be empty")
}
if t, e := tEvalFn(cpb.TraceId); e != nil || t != istio_mixer_v1_config_descriptor.STRING {
if e != nil {
return nil, fmt.Errorf("failed to evaluate expression for field TraceId: %v", e)
}
return nil, fmt.Errorf("error type checking for field TraceId: Evaluated expression type %v want %v", t, istio_mixer_v1_config_descriptor.STRING)
}

if cpb.SpanId == "" || cpb.SpanId == emptyQuotes {
return nil, errors.New("expression for field SpanId cannot be empty")
}
if t, e := tEvalFn(cpb.SpanId); e != nil || t != istio_mixer_v1_config_descriptor.STRING {
if e != nil {
return nil, fmt.Errorf("failed to evaluate expression for field SpanId: %v", e)
}
return nil, fmt.Errorf("error type checking for field SpanId: Evaluated expression type %v want %v", t, istio_mixer_v1_config_descriptor.STRING)
}

if cpb.ParentSpanId == "" || cpb.ParentSpanId == emptyQuotes {
return nil, errors.New("expression for field ParentSpanId cannot be empty")
}
if t, e := tEvalFn(cpb.ParentSpanId); e != nil || t != istio_mixer_v1_config_descriptor.STRING {
if e != nil {
return nil, fmt.Errorf("failed to evaluate expression for field ParentSpanId: %v", e)
}
return nil, fmt.Errorf("error type checking for field ParentSpanId: Evaluated expression type %v want %v", t, istio_mixer_v1_config_descriptor.STRING)
}

if cpb.SpanName == "" || cpb.SpanName == emptyQuotes {
return nil, errors.New("expression for field SpanName cannot be empty")
}
if t, e := tEvalFn(cpb.SpanName); e != nil || t != istio_mixer_v1_config_descriptor.STRING {
if e != nil {
return nil, fmt.Errorf("failed to evaluate expression for field SpanName: %v", e)
}
return nil, fmt.Errorf("error type checking for field SpanName: Evaluated expression type %v want %v", t, istio_mixer_v1_config_descriptor.STRING)
}

if cpb.StartTime == "" || cpb.StartTime == emptyQuotes {
return nil, errors.New("expression for field StartTime cannot be empty")
}
if t, e := tEvalFn(cpb.StartTime); e != nil || t != istio_mixer_v1_config_descriptor.TIMESTAMP {
if e != nil {
return nil, fmt.Errorf("failed to evaluate expression for field StartTime: %v", e)
}
return nil, fmt.Errorf("error type checking for field StartTime: Evaluated expression type %v want %v", t, istio_mixer_v1_config_descriptor.TIMESTAMP)
}

if cpb.EndTime == "" || cpb.EndTime == emptyQuotes {
return nil, errors.New("expression for field EndTime cannot be empty")
}
if t, e := tEvalFn(cpb.EndTime); e != nil || t != istio_mixer_v1_config_descriptor.TIMESTAMP {
if e != nil {
return nil, fmt.Errorf("failed to evaluate expression for field EndTime: %v", e)
}
return nil, fmt.Errorf("error type checking for field EndTime: Evaluated expression type %v want %v", t, istio_mixer_v1_config_descriptor.TIMESTAMP)
}

infrdType.SpanTags = make(map[string]istio_mixer_v1_config_descriptor.ValueType, len(cpb.SpanTags))
for k, v := range cpb.SpanTags {
if infrdType.SpanTags[k], err = tEvalFn(v); err != nil {
return nil, err
}
}

_ = cpb
return infrdType, err
},
SetType: func(types map[string]proto.Message, builder adapter.HandlerBuilder) {
// Mixer framework should have ensured the type safety.
castedBuilder := builder.(tracespan.HandlerBuilder)
castedTypes := make(map[string]*tracespan.Type, len(types))
for k, v := range types {
// Mixer framework should have ensured the type safety.
v1 := v.(*tracespan.Type)
castedTypes[k] = v1
}
castedBuilder.SetTraceSpanTypes(castedTypes)
},

ProcessReport: func(ctx context.Context, insts map[string]proto.Message, attrs attribute.Bag, mapper expr.Evaluator, handler adapter.Handler) error {
var instances []*tracespan.Instance
for name, inst := range insts {
md := inst.(*tracespan.InstanceParam)

TraceId, err := mapper.Eval(md.TraceId, attrs)

if err != nil {
msg := fmt.Sprintf("failed to eval TraceId for instance '%s': %v", name, err)
glog.Error(msg)
return errors.New(msg)
}

SpanId, err := mapper.Eval(md.SpanId, attrs)

if err != nil {
msg := fmt.Sprintf("failed to eval SpanId for instance '%s': %v", name, err)
glog.Error(msg)
return errors.New(msg)
}

ParentSpanId, err := mapper.Eval(md.ParentSpanId, attrs)

if err != nil {
msg := fmt.Sprintf("failed to eval ParentSpanId for instance '%s': %v", name, err)
glog.Error(msg)
return errors.New(msg)
}

SpanName, err := mapper.Eval(md.SpanName, attrs)

if err != nil {
msg := fmt.Sprintf("failed to eval SpanName for instance '%s': %v", name, err)
glog.Error(msg)
return errors.New(msg)
}

StartTime, err := mapper.Eval(md.StartTime, attrs)

if err != nil {
msg := fmt.Sprintf("failed to eval StartTime for instance '%s': %v", name, err)
glog.Error(msg)
return errors.New(msg)
}

EndTime, err := mapper.Eval(md.EndTime, attrs)

if err != nil {
msg := fmt.Sprintf("failed to eval EndTime for instance '%s': %v", name, err)
glog.Error(msg)
return errors.New(msg)
}

SpanTags, err := template.EvalAll(md.SpanTags, attrs, mapper)

if err != nil {
msg := fmt.Sprintf("failed to eval SpanTags for instance '%s': %v", name, err)
glog.Error(msg)
return errors.New(msg)
}

instances = append(instances, &tracespan.Instance{
Name: name,

TraceId: TraceId.(string),

SpanId: SpanId.(string),

ParentSpanId: ParentSpanId.(string),

SpanName: SpanName.(string),

StartTime: StartTime.(time.Time),

EndTime: EndTime.(time.Time),

SpanTags: SpanTags,
})
_ = md
}

if err := handler.(tracespan.Handler).HandleTraceSpan(ctx, instances); err != nil {
return fmt.Errorf("failed to report all values: %v", err)
}
return nil
},
},
}
)
8 changes: 8 additions & 0 deletions mixer/template/tracespan/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package(default_visibility = ["//visibility:public"])

load("//mixer/tools/codegen:generate.bzl", "mixer_proto_library")

mixer_proto_library(
name = "go_default_library",
protos = ["tracespan.proto"],
)
143 changes: 143 additions & 0 deletions mixer/template/tracespan/go_default_library_handler.gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright 2017 Istio Authors
//
// 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.

// THIS FILE IS AUTOMATICALLY GENERATED.

package tracespan

import (
"context"
"time"

"istio.io/istio/mixer/pkg/adapter"
)

// Fully qualified name of the template
const TemplateName = "tracespan"

// Instance is constructed by Mixer for the 'tracespan' template.
//
// TraceSpan represents an individual span within a distributed trace.
//
// When writing the configuration, the value for the fields associated with this template can either be a
// literal or an [expression](https://istio.io/docs/reference/config/mixer/expression-language.html). Please note that if the datatype of a field is not istio.mixer.v1.config.descriptor.ValueType,
// then the expression's [inferred type](https://istio.io/docs/reference/config/mixer/expression-language.html#type-checking) must match the datatype of the field.
//
// Example config:
// ```
// apiVersion: "config.istio.io/v1alpha2"
// kind: tracespan
// metadata:
// name: default
// namespace: istio-system
// spec:
// traceId: request.headers["x-b3-traceid"]
// spanId: request.headers["x-b3-spanid"] | ""
// parentSpanId: request.headers["x-b3-parentspanid"] | ""
// spanName: request.path | "/"
// startTime: request.time
// endTime: response.time
// spanTags:
// http.method: request.method | ""
// http.status_code: response.code | 200
// http.url: request.path | ""
// request.size: request.size | 0
// response.size: response.size | 0
// source.ip: source.ip | ip("0.0.0.0")
// source.service: source.service | ""
// source.user: source.user | ""
// source.version: source.labels["version"] | ""
// ```
//
// See also: [Distributed Tracing](https://istio.io/docs/tasks/telemetry/distributed-tracing.html)
// for information on tracing within Istio.
type Instance struct {
// Name of the instance as specified in configuration.
Name string

// Trace ID is the unique identifier for a trace. All spans from the same
// trace share the same Trace ID.
//
// Required.
TraceId string

// Span ID is the unique identifier for a span within a trace. It is assigned
// when the span is created.
//
// Optional.
SpanId string

// Parent Span ID is the unique identifier for a parent span of this span
// instance. If this is a root span, then this field MUST be empty.
//
// Optional.
ParentSpanId string

// Span name is a description of the span's operation.
//
// For example, the name can be a qualified method name or a file name
// and a line number where the operation is called. A best practice is to use
// the same display name within an application and at the same call point.
// This makes it easier to correlate spans in different traces.
//
// Required.
SpanName string

// The start time of the span.
//
// Required.
StartTime time.Time

// The end time of the span.
//
// Required.
EndTime time.Time

// Span tags are a set of <key, value> pairs that provide metadata for the
// entire span. The values can be specified in the form of expressions.
//
// Optional.
SpanTags map[string]interface{}
}

// HandlerBuilder must be implemented by adapters if they want to
// process data associated with the 'tracespan' template.
//
// Mixer uses this interface to call into the adapter at configuration time to configure
// it with adapter-specific configuration as well as all template-specific type information.
type HandlerBuilder interface {
adapter.HandlerBuilder

// SetTraceSpanTypes is invoked by Mixer to pass the template-specific Type information for instances that an adapter
// may receive at runtime. The type information describes the shape of the instance.
SetTraceSpanTypes(map[string]*Type /*Instance name -> Type*/)
}

// Handler must be implemented by adapter code if it wants to
// process data associated with the 'tracespan' template.
//
// Mixer uses this interface to call into the adapter at request time in order to dispatch
// created instances to the adapter. Adapters take the incoming instances and do what they
// need to achieve their primary function.
//
// The name of each instance can be used as a key into the Type map supplied to the adapter
// at configuration time via the method 'SetTraceSpanTypes'.
// These Type associated with an instance describes the shape of the instance
type Handler interface {
adapter.Handler

// HandleTraceSpan is called by Mixer at request time to deliver instances to
// to an adapter.
HandleTraceSpan(context.Context, []*Instance) error
}
Loading

0 comments on commit df6649a

Please sign in to comment.