github.com/instana/go-sensor@v1.62.2-0.20240520081010-4919868049e1/gcr_agent_test.go (about)

     1  // (c) Copyright IBM Corp. 2021
     2  // (c) Copyright Instana Inc. 2020
     3  
     4  //go:build gcr && integration
     5  // +build gcr,integration
     6  
     7  package instana_test
     8  
     9  import (
    10  	"context"
    11  	"encoding/json"
    12  	"log"
    13  	"net/http"
    14  	"net/http/httptest"
    15  	"os"
    16  	"testing"
    17  	"time"
    18  
    19  	instana "github.com/instana/go-sensor"
    20  	"github.com/stretchr/testify/assert"
    21  	"github.com/stretchr/testify/require"
    22  )
    23  
    24  var agent *serverlessAgent
    25  
    26  func TestMain(m *testing.M) {
    27  	teardownEnv := setupGCREnv()
    28  	defer teardownEnv()
    29  
    30  	teardownSrv := setupMetadataServer()
    31  	defer teardownSrv()
    32  
    33  	defer restoreEnvVarFunc("INSTANA_AGENT_KEY")
    34  	os.Setenv("INSTANA_AGENT_KEY", "testkey1")
    35  
    36  	defer restoreEnvVarFunc("INSTANA_ZONE")
    37  	os.Setenv("INSTANA_ZONE", "testzone")
    38  
    39  	defer restoreEnvVarFunc("INSTANA_TAGS")
    40  	os.Setenv("INSTANA_TAGS", "key1=value1,key2")
    41  
    42  	defer restoreEnvVarFunc("INSTANA_SECRETS")
    43  	os.Setenv("INSTANA_SECRETS", "contains-ignore-case:key,password,secret,classified")
    44  
    45  	defer restoreEnvVarFunc("CLASSIFIED_DATA")
    46  	os.Setenv("CLASSIFIED_DATA", "classified")
    47  
    48  	var err error
    49  	agent, err = setupServerlessAgent()
    50  	if err != nil {
    51  		log.Fatalf("failed to initialize serverless agent: %s", err)
    52  	}
    53  
    54  	instana.InitSensor(instana.DefaultOptions())
    55  
    56  	os.Exit(m.Run())
    57  }
    58  
    59  func TestGCRAgent_SendMetrics(t *testing.T) {
    60  	defer agent.Reset()
    61  
    62  	require.Eventually(t, func() bool { return len(agent.Bundles) > 0 }, 2*time.Second, 500*time.Millisecond)
    63  
    64  	collected := agent.Bundles[0]
    65  
    66  	assert.Equal(t, "gcp:cloud-run:revision:test-revision", collected.Header.Get("X-Instana-Host"))
    67  	assert.Equal(t, "testkey1", collected.Header.Get("X-Instana-Key"))
    68  	assert.NotEmpty(t, collected.Header.Get("X-Instana-Time"))
    69  
    70  	var payload struct {
    71  		Metrics struct {
    72  			Plugins []struct {
    73  				Name     string                 `json:"name"`
    74  				EntityID string                 `json:"entityId"`
    75  				Data     map[string]interface{} `json:"data"`
    76  			} `json:"plugins"`
    77  		} `json:"metrics"`
    78  	}
    79  	require.NoError(t, json.Unmarshal(collected.Body, &payload))
    80  
    81  	pluginData := make(map[string][]serverlessAgentPluginPayload)
    82  	for _, plugin := range payload.Metrics.Plugins {
    83  		pluginData[plugin.Name] = append(pluginData[plugin.Name], serverlessAgentPluginPayload{plugin.EntityID, plugin.Data})
    84  	}
    85  
    86  	t.Run("GCR service revision instance plugin payload", func(t *testing.T) {
    87  		require.Len(t, pluginData["com.instana.plugin.gcp.run.revision.instance"], 1)
    88  		d := pluginData["com.instana.plugin.gcp.run.revision.instance"][0]
    89  
    90  		assert.Equal(t, "id1", d.EntityID)
    91  
    92  		assert.Equal(t, "go", d.Data["runtime"])
    93  		assert.Equal(t, "us-central1", d.Data["region"])
    94  		assert.Equal(t, "test-service", d.Data["service"])
    95  		assert.Equal(t, "test-configuration", d.Data["configuration"])
    96  		assert.Equal(t, "test-revision", d.Data["revision"])
    97  		assert.Equal(t, "id1", d.Data["instanceId"])
    98  		assert.Equal(t, "8081", d.Data["port"])
    99  		assert.EqualValues(t, 1234567890, d.Data["numericProjectId"])
   100  		assert.Equal(t, "test-project", d.Data["projectId"])
   101  	})
   102  
   103  	t.Run("Process plugin payload", func(t *testing.T) {
   104  		require.Len(t, pluginData["com.instana.plugin.process"], 1)
   105  		d := pluginData["com.instana.plugin.process"][0]
   106  
   107  		assert.NotEmpty(t, d.EntityID)
   108  
   109  		assert.Equal(t, "gcpCloudRunInstance", d.Data["containerType"])
   110  		assert.Equal(t, "id1", d.Data["container"])
   111  		assert.Equal(t, "gcp:cloud-run:revision:test-revision", d.Data["com.instana.plugin.host.name"])
   112  
   113  		if assert.IsType(t, map[string]interface{}{}, d.Data["env"]) {
   114  			env := d.Data["env"].(map[string]interface{})
   115  
   116  			assert.Equal(t, os.Getenv("INSTANA_ZONE"), env["INSTANA_ZONE"])
   117  			assert.Equal(t, os.Getenv("INSTANA_TAGS"), env["INSTANA_TAGS"])
   118  			assert.Equal(t, os.Getenv("INSTANA_AGENT_KEY"), env["INSTANA_AGENT_KEY"])
   119  
   120  			assert.Equal(t, "<redacted>", env["INSTANA_SECRETS"])
   121  			assert.Equal(t, "<redacted>", env["CLASSIFIED_DATA"])
   122  		}
   123  	})
   124  
   125  	t.Run("Go process plugin payload", func(t *testing.T) {
   126  		require.Len(t, pluginData["com.instana.plugin.golang"], 1)
   127  		d := pluginData["com.instana.plugin.golang"][0]
   128  
   129  		assert.NotEmpty(t, d.EntityID)
   130  
   131  		require.NotEmpty(t, pluginData["com.instana.plugin.process"])
   132  		assert.Equal(t, pluginData["com.instana.plugin.process"][0].EntityID, d.EntityID)
   133  
   134  		assert.NotEmpty(t, d.Data["metrics"])
   135  	})
   136  }
   137  
   138  func TestGCRAgent_SendSpans(t *testing.T) {
   139  	defer agent.Reset()
   140  
   141  	sensor := instana.NewSensor("testing")
   142  
   143  	sp := sensor.Tracer().StartSpan("entry")
   144  	sp.SetTag("value", "42")
   145  	sp.Finish()
   146  
   147  	require.Eventually(t, func() bool {
   148  		if len(agent.Bundles) == 0 {
   149  			return false
   150  		}
   151  
   152  		for _, bundle := range agent.Bundles {
   153  			var payload struct {
   154  				Spans []json.RawMessage `json:"spans"`
   155  			}
   156  
   157  			json.Unmarshal(bundle.Body, &payload)
   158  			if len(payload.Spans) > 0 {
   159  				return true
   160  			}
   161  		}
   162  
   163  		return false
   164  	}, 4*time.Second, 500*time.Millisecond)
   165  
   166  	var spans []map[string]json.RawMessage
   167  	for _, bundle := range agent.Bundles {
   168  		var payload struct {
   169  			Spans []map[string]json.RawMessage `json:"spans"`
   170  		}
   171  
   172  		require.NoError(t, json.Unmarshal(bundle.Body, &payload), "%s", string(bundle.Body))
   173  		spans = append(spans, payload.Spans...)
   174  	}
   175  
   176  	require.Len(t, spans, 1)
   177  	assert.JSONEq(t, `{"hl": true, "cp": "gcp", "e": "id1"}`, string(spans[0]["f"]))
   178  }
   179  
   180  func TestGCRAgent_FlushSpans(t *testing.T) {
   181  	defer agent.Reset()
   182  
   183  	tracer := instana.NewTracer()
   184  	sensor := instana.NewSensorWithTracer(tracer)
   185  
   186  	sp := sensor.Tracer().StartSpan("entry")
   187  	sp.SetTag("value", "42")
   188  	sp.Finish()
   189  
   190  	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
   191  	defer cancel()
   192  
   193  	require.NoError(t, tracer.Flush(ctx))
   194  }
   195  
   196  func setupGCREnv() func() {
   197  	var teardownFns []func()
   198  
   199  	teardownFns = append(teardownFns, restoreEnvVarFunc("K_SERVICE"))
   200  	os.Setenv("K_SERVICE", "test-service")
   201  
   202  	teardownFns = append(teardownFns, restoreEnvVarFunc("K_CONFIGURATION"))
   203  	os.Setenv("K_CONFIGURATION", "test-configuration")
   204  
   205  	teardownFns = append(teardownFns, restoreEnvVarFunc("K_REVISION"))
   206  	os.Setenv("K_REVISION", "test-revision")
   207  
   208  	teardownFns = append(teardownFns, restoreEnvVarFunc("PORT"))
   209  	os.Setenv("PORT", "8081")
   210  
   211  	return func() {
   212  		for _, fn := range teardownFns {
   213  			fn()
   214  		}
   215  	}
   216  }
   217  
   218  func setupMetadataServer() func() {
   219  	mux := http.NewServeMux()
   220  	mux.HandleFunc("/computeMetadata/v1", func(w http.ResponseWriter, req *http.Request) {
   221  		http.ServeFile(w, req, "gcloud/testdata/computeMetadata.json")
   222  	})
   223  
   224  	srv := httptest.NewServer(mux)
   225  
   226  	teardown := restoreEnvVarFunc("GOOGLE_CLOUD_RUN_METADATA_ENDPOINT")
   227  	os.Setenv("GOOGLE_CLOUD_RUN_METADATA_ENDPOINT", srv.URL)
   228  
   229  	return func() {
   230  		teardown()
   231  		srv.Close()
   232  	}
   233  }