Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
5d736d9b
Commit
5d736d9b
authored
Oct 23, 2020
by
Matthias Kaeppler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add a total-requests metric for the image scaler
Broken down by a `status` label
parent
b5dab707
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
38 additions
and
16 deletions
+38
-16
changelogs/unreleased/mk-image-scaler-total-requests-metric.yml
...logs/unreleased/mk-image-scaler-total-requests-metric.yml
+5
-0
internal/imageresizer/image_resizer.go
internal/imageresizer/image_resizer.go
+33
-16
No files found.
changelogs/unreleased/mk-image-scaler-total-requests-metric.yml
0 → 100644
View file @
5d736d9b
---
title
:
Add a total requests metric for image scaling
merge_request
:
638
author
:
type
:
other
internal/imageresizer/image_resizer.go
View file @
5d736d9b
...
...
@@ -43,6 +43,15 @@ type processCounter struct {
n
int32
}
type
resizeStatus
=
string
const
(
statusSuccess
=
"success"
// a rescaled image was served
statusScalingFailure
=
"scaling-failed"
// scaling failed but the original image was served
statusRequestFailure
=
"request-failed"
// no image was served
statusUnknown
=
"unknown"
// indicates an unhandled status case
)
var
envInjector
=
tracing
.
NewEnvInjector
()
// Images might be located remotely in object storage, in which case we need to stream
...
...
@@ -86,13 +95,14 @@ var (
Help
:
"Amount of image resizing scaler processes working now"
,
},
)
imageResize
Completed
=
prometheus
.
NewCounter
(
imageResize
Requests
=
prometheus
.
NewCounterVec
(
prometheus
.
CounterOpts
{
Namespace
:
namespace
,
Subsystem
:
subsystem
,
Name
:
"
completed
_total"
,
Help
:
"
Amount of image resizing processes sucessfully comple
ted"
,
Name
:
"
requests
_total"
,
Help
:
"
Image resizing operations reques
ted"
,
},
[]
string
{
"status"
},
)
imageResizeDurations
=
prometheus
.
NewHistogramVec
(
prometheus
.
HistogramOpts
{
...
...
@@ -116,7 +126,7 @@ var (
func
init
()
{
prometheus
.
MustRegister
(
imageResizeConcurrencyLimitExceeds
)
prometheus
.
MustRegister
(
imageResizeProcesses
)
prometheus
.
MustRegister
(
imageResize
Completed
)
prometheus
.
MustRegister
(
imageResize
Requests
)
prometheus
.
MustRegister
(
imageResizeDurations
)
}
...
...
@@ -127,12 +137,18 @@ func NewResizer(cfg config.Config) *Resizer {
// This Injecter forks into a dedicated scaler process to resize an image identified by path or URL
// and streams the resized image back to the client
func
(
r
*
Resizer
)
Inject
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
,
paramsData
string
)
{
var
status
resizeStatus
=
statusUnknown
defer
func
()
{
imageResizeRequests
.
WithLabelValues
(
status
)
.
Inc
()
}()
start
:=
time
.
Now
()
logger
:=
log
.
ContextLogger
(
req
.
Context
())
params
,
err
:=
r
.
unpackParameters
(
paramsData
)
if
err
!=
nil
{
// This means the response header coming from Rails was malformed; there is no way
// to sensibly recover from this other than failing fast
status
=
statusRequestFailure
helper
.
Fail500
(
w
,
req
,
fmt
.
Errorf
(
"ImageResizer: Failed reading image resize params: %v"
,
err
))
return
}
...
...
@@ -140,6 +156,7 @@ func (r *Resizer) Inject(w http.ResponseWriter, req *http.Request, paramsData st
sourceImageReader
,
fileSize
,
err
:=
openSourceImage
(
params
.
Location
)
if
err
!=
nil
{
// This means we cannot even read the input image; fail fast.
status
=
statusRequestFailure
helper
.
Fail500
(
w
,
req
,
fmt
.
Errorf
(
"ImageResizer: Failed opening image data stream: %v"
,
err
))
return
}
...
...
@@ -159,22 +176,28 @@ func (r *Resizer) Inject(w http.ResponseWriter, req *http.Request, paramsData st
// will point to the original image, i.e. we render it unchanged.
imageReader
,
resizeCmd
,
err
:=
r
.
tryResizeImage
(
req
,
sourceImageReader
,
logger
.
Writer
(),
params
,
fileSize
,
r
.
Config
.
ImageResizerConfig
)
if
err
!=
nil
{
//
something failed, but we can still write out the original image, do don't return early
//
Something failed, but we can still write out the original image, so don't return early.
helper
.
LogErrorWithFields
(
req
,
err
,
*
logFields
(
0
))
}
defer
helper
.
CleanUpProcessGroup
(
resizeCmd
)
imageResizeCompleted
.
Inc
()
w
.
Header
()
.
Del
(
"Content-Length"
)
bytesWritten
,
err
:=
serveImage
(
imageReader
,
w
,
resizeCmd
)
// We failed serving image data; this is a hard failure.
if
err
!=
nil
{
handleFailedCommand
(
w
,
req
,
bytesWritten
,
err
,
logFields
(
bytesWritten
))
status
=
statusRequestFailure
if
bytesWritten
<=
0
{
helper
.
Fail500
(
w
,
req
,
err
)
}
else
{
helper
.
LogErrorWithFields
(
req
,
err
,
*
logFields
(
bytesWritten
))
}
return
}
// This means we served the original image because rescaling failed; this is a soft failure
if
resizeCmd
==
nil
{
// This means we served the original image because rescaling failed
status
=
statusScalingFailure
logger
.
WithFields
(
*
logFields
(
bytesWritten
))
.
Printf
(
"ImageResizer: Served original"
)
return
}
...
...
@@ -183,6 +206,8 @@ func (r *Resizer) Inject(w http.ResponseWriter, req *http.Request, paramsData st
imageResizeDurations
.
WithLabelValues
(
params
.
ContentType
,
widthLabelVal
)
.
Observe
(
time
.
Since
(
start
)
.
Seconds
())
logger
.
WithFields
(
*
logFields
(
bytesWritten
))
.
Printf
(
"ImageResizer: Success"
)
status
=
statusSuccess
}
// Streams image data from the given reader to the given writer and returns the number of bytes written.
...
...
@@ -201,14 +226,6 @@ func serveImage(r io.Reader, w io.Writer, resizeCmd *exec.Cmd) (int64, error) {
return
bytesWritten
,
nil
}
func
handleFailedCommand
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
,
bytesWritten
int64
,
err
error
,
logFields
*
log
.
Fields
)
{
if
bytesWritten
<=
0
{
helper
.
Fail500
(
w
,
req
,
err
)
}
else
{
helper
.
LogErrorWithFields
(
req
,
err
,
*
logFields
)
}
}
func
(
r
*
Resizer
)
unpackParameters
(
paramsData
string
)
(
*
resizeParams
,
error
)
{
var
params
resizeParams
if
err
:=
r
.
Unpack
(
&
params
,
paramsData
);
err
!=
nil
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment