Skip to content

Commit

Permalink
[apmazure] storage queue (#1107)
Browse files Browse the repository at this point in the history
add azure queue storage instrumentation
  • Loading branch information
stuartnelson3 authored Aug 24, 2021
1 parent 2a0dae9 commit 4173391
Show file tree
Hide file tree
Showing 9 changed files with 430 additions and 23 deletions.
1 change: 1 addition & 0 deletions docs/instrumenting.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,7 @@ can be used as normal.
The following services are supported:

- Blob Storage
- Queue Storage


[source,go]
Expand Down
6 changes: 4 additions & 2 deletions docs/supported-tech.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,10 @@ about AWS SDK Go instrumentation.

[float]
==== Azure Storage
We provide instrumentation for Azure Storage. This is usable with
github.com/Azure/azure-storage-blob-go/azblob[Azure Blob Storage].
We provide instrumentation for Azure Storage. This is usable with:

- github.com/Azure/azure-storage-blob-go/azblob[Azure Blob Storage]
- github.com/Azure/azure-storage-queue-go/azqueue[Azure Queue Storage]

See <<builtin-modules-apmazure, module/apmazure>> for more information
about Azure SDK Go instrumentation.
Expand Down
18 changes: 10 additions & 8 deletions module/apmazure/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,19 @@ func (b *blobRPC) operation() string {
// From net/http documentation:
// For client requests, an empty string means GET.
case http.MethodGet, "":
return getOperation(q)
return b.getOperation(q)
case http.MethodPost:
return postOperation(q)
return b.postOperation(q)
case http.MethodHead:
return headOperation(q)
return b.headOperation(q)
case http.MethodPut:
return putOperation(q, b.req.Header)
return b.putOperation(q, b.req.Header)
default:
return b.req.Method
}
}

func getOperation(v url.Values) string {
func (b *blobRPC) getOperation(v url.Values) string {
restype := v.Get("restype")
comp := v.Get("comp")
if (restype == "" && comp == "") || comp == "blocklist" {
Expand Down Expand Up @@ -106,7 +106,7 @@ func getOperation(v url.Values) string {
}
}

func postOperation(v url.Values) string {
func (b *blobRPC) postOperation(v url.Values) string {
comp := v.Get("comp")
switch comp {
case "batch":
Expand All @@ -120,7 +120,8 @@ func postOperation(v url.Values) string {
}

}
func headOperation(v url.Values) string {

func (b *blobRPC) headOperation(v url.Values) string {
restype := v.Get("restype")
comp := v.Get("comp")
if restype == "" && comp == "" {
Expand All @@ -138,7 +139,8 @@ func headOperation(v url.Values) string {
return "unknown operation"
}
}
func putOperation(v url.Values, h http.Header) string {

func (b *blobRPC) putOperation(v url.Values, h http.Header) string {
// header.Get canonicalizes the key, ie. x-ms-copy-source->X-Ms-Copy-Source.
// The headers used are all lowercase, so we access the map directly.
_, copySource := h["x-ms-copy-source"]
Expand Down
20 changes: 12 additions & 8 deletions module/apmazure/blob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TestBlob(t *testing.T) {
assert.Equal(t, "azureblob/fakeaccnt", destination.Service.Resource)
}

func TestGetOperation(t *testing.T) {
func TestBlobGetOperation(t *testing.T) {
tcs := []struct {
want string
values url.Values
Expand Down Expand Up @@ -110,12 +110,13 @@ func TestGetOperation(t *testing.T) {
},
}

b := new(blobRPC)
for _, tc := range tcs {
assert.Equal(t, tc.want, getOperation(tc.values))
assert.Equal(t, tc.want, b.getOperation(tc.values))
}
}

func TestHeadOperation(t *testing.T) {
func TestBlobHeadOperation(t *testing.T) {
tcs := []struct {
want string
values url.Values
Expand All @@ -135,12 +136,13 @@ func TestHeadOperation(t *testing.T) {
},
}

b := new(blobRPC)
for _, tc := range tcs {
assert.Equal(t, tc.want, headOperation(tc.values))
assert.Equal(t, tc.want, b.headOperation(tc.values))
}
}

func TestPostOperation(t *testing.T) {
func TestBlobPostOperation(t *testing.T) {
tcs := []struct {
want string
values url.Values
Expand All @@ -164,12 +166,13 @@ func TestPostOperation(t *testing.T) {
},
}

b := new(blobRPC)
for _, tc := range tcs {
assert.Equal(t, tc.want, postOperation(tc.values))
assert.Equal(t, tc.want, b.postOperation(tc.values))
}
}

func TestPutOperation(t *testing.T) {
func TestBlobPutOperation(t *testing.T) {
tcs := []struct {
want string
values url.Values
Expand Down Expand Up @@ -280,8 +283,9 @@ func TestPutOperation(t *testing.T) {
},
}

b := new(blobRPC)
for _, tc := range tcs {
assert.Equal(t, tc.want, putOperation(tc.values, tc.header))
assert.Equal(t, tc.want, b.putOperation(tc.values, tc.header))
}
}

Expand Down
1 change: 1 addition & 0 deletions module/apmazure/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.14
require (
github.com/Azure/azure-pipeline-go v0.2.3
github.com/Azure/azure-storage-blob-go v0.14.0
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd
github.com/stretchr/testify v1.7.0
go.elastic.co/apm v1.13.1
go.elastic.co/apm/module/apmhttp v1.13.1
Expand Down
4 changes: 4 additions & 0 deletions module/apmazure/go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U=
github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k=
github.com/Azure/azure-storage-blob-go v0.14.0 h1:1BCg74AmVdYwO3dlKwtFU1V0wU2PZdREkXvAmZJRUlM=
github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck=
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd h1:b3wyxBl3vvr15tUAziPBPK354y+LSdfPCpex5oBttHo=
github.com/Azure/azure-storage-queue-go v0.0.0-20191125232315-636801874cdd/go.mod h1:K6am8mT+5iFXgingS9LUc7TmbsW6XBw3nxaRyaMyWc8=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q=
Expand Down Expand Up @@ -104,6 +107,7 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
Expand Down
135 changes: 135 additions & 0 deletions module/apmazure/queue.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// 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.

//go:build go1.14
// +build go1.14

package apmazure // import "go.elastic.co/apm/module/apmazure"

import (
"fmt"
"net/http"
"net/url"
"strings"

"github.com/Azure/azure-pipeline-go/pipeline"
)

type queueRPC struct {
accountName string
resourceName string
req pipeline.Request
}

func (q *queueRPC) name() string {
return fmt.Sprintf("AzureQueue %s %s %s", q.operation(), q.dir(), q.accountName)
}

func (q *queueRPC) _type() string {
return "messaging"
}

func (q *queueRPC) subtype() string {
return "azurequeue"
}

func (q *queueRPC) storageAccountName() string {
return q.accountName
}

func (q *queueRPC) resource() string {
return q.resourceName
}

func (q *queueRPC) dir() string {
switch q.req.Method {
case http.MethodGet, "":
return "from"
default:
return "to"
}
}

func (q *queueRPC) operation() string {
query := q.req.URL.Query()
switch q.req.Method {
// From net/http documentation:
// For client requests, an empty string means GET.
case http.MethodGet, "":
return q.getOperation(query)
case http.MethodPost:
return q.postOperation(query)
case http.MethodHead:
return q.headOperation(query)
case http.MethodPut:
return q.putOperation(query)
case http.MethodOptions:
return "PREFLIGHT"
case http.MethodDelete:
if strings.HasSuffix(q.req.URL.Path, "/messages") {
return "CLEAR"
}
return "DELETE"
default:
return q.req.Method
}
}

func (q *queueRPC) getOperation(v url.Values) string {
if peekOnly := v.Get("peekonly"); peekOnly == "true" {
return "PEEK"
}
switch comp := v.Get("comp"); comp {
case "":
return "RECEIVE"
case "list":
return "LISTQUEUES"
case "stats":
return "STATS"
case "properties", "metadata", "acl":
return "GET" + strings.ToUpper(comp)
default:
return "unknown operation"
}
}

func (q *queueRPC) postOperation(v url.Values) string {
return "SEND"
}

func (q *queueRPC) headOperation(v url.Values) string {
switch comp := v.Get("comp"); comp {
case "metadata", "acl":
return "GET" + strings.ToUpper(comp)
default:
return "unknown operation"
}
}

func (q *queueRPC) putOperation(v url.Values) string {
if _, ok := v["popreceipt"]; ok {
return "UPDATE"
}
switch comp := v.Get("comp"); comp {
case "":
return "CREATE"
case "metadata", "acl", "properties":
return "SET" + strings.ToUpper(comp)
default:
return "unknown operation"
}
}
Loading

0 comments on commit 4173391

Please sign in to comment.