accumulator/invocation.go (39 lines of code) (raw):
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you 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 accumulator
import (
"time"
"github.com/tidwall/sjson"
)
// Invocation holds data for each function invocation and finalizes
// the data when `platform.report` type log is received for the
// specific invocation identified by request ID.
type Invocation struct {
// RequestID is the id to identify the invocation.
RequestID string
// Timestamp is the time of the invocation.
Timestamp time.Time
// DeadlineMs is the function execution deadline.
DeadlineMs int64
// FunctionARN requested. Can be different in each invoke that
// executes the same version.
FunctionARN string
// TransactionID is the ID generated for a transaction for the
// current invocation. It is populated by the request from agent.
TransactionID string
// AgentPayload is the partial transaction registered at agent init.
// It will be used to create a proxy transaction by enriching the
// payload with data from `platform.runtimeDone` event if agent fails
// to report the actual transaction.
AgentPayload []byte
// TransactionObserved is true if the root transaction ID for the
// invocation is observed by the extension.
TransactionObserved bool
// Finalized tracks if the invocation has been finalized or not.
Finalized bool
}
// NeedProxyTransaction returns true if a proxy transaction needs to be
// created based on the information available.
func (inc *Invocation) NeedProxyTransaction() bool {
return !inc.Finalized && inc.TransactionID != "" && !inc.TransactionObserved
}
// MaybeCreateProxyTxn creates a proxy transaction for an invocation
// if required. A proxy transaction will be required to be created
// if the agent has registered a transaction for the invocation but
// has not sent the corresponding transaction to the extension. The
// proxy transaction will not be created if the invocation has
// already been finalized or the agent has reported the transaction.
func (inc *Invocation) MaybeCreateProxyTxn(status string, endTime time.Time) ([]byte, error) {
if !inc.NeedProxyTransaction() {
return nil, nil
}
txn, err := sjson.SetBytes(inc.AgentPayload, "transaction.result", status)
if err != nil {
return nil, err
}
// Transaction duration cannot be known in partial transaction payload. Estimate
// the duration based on the time provided. Time can be based on the runtimeDone
// log record or function deadline.
duration := endTime.Sub(inc.Timestamp)
txn, err = sjson.SetBytes(txn, "transaction.duration", duration.Milliseconds())
if err != nil {
return nil, err
}
if status != "success" {
txn, err = sjson.SetBytes(txn, "transaction.outcome", "failure")
if err != nil {
return nil, err
}
}
return txn, nil
}